From 7474cdb8b6b2cf198d0ec02b0cb8670862954c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Tue, 20 Mar 2012 11:24:05 +0100 Subject: [PATCH] Fixed member reference expression bug. --- .../Completion/CSharpCompletionEngine.cs | 81 +++++++++++-------- .../CodeCompletion/CodeCompletionBugTests.cs | 22 +++++ 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs index 6e130aa1d6..e826a9a9e4 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -189,6 +189,29 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } } + IEnumerable HandleMemberReferenceCompletion(ExpressionResult expr) + { + if (expr == null) + return null; + + // do not complete . (but ..) + if (expr.Node is PrimitiveExpression) { + var pexpr = (PrimitiveExpression)expr.Node; + if (!(pexpr.Value is string || pexpr.Value is char) && !pexpr.LiteralValue.Contains('.')) { + return null; + } + } + + var resolveResult = ResolveExpression (expr); + if (resolveResult == null) { + return null; + } + if (expr.Node is AstType) { + return CreateTypeAndNamespaceCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2); + } + return CreateCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2); + } + IEnumerable MagicKeyCompletion(char completionChar, bool controlSpace) { ExpressionResult expr; @@ -201,26 +224,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (IsInsideCommentOrString()) { return Enumerable.Empty(); } - expr = GetExpressionBeforeCursor(); - if (expr == null) { - return null; - } - // do not complete . (but ..) - if (expr.Node is PrimitiveExpression) { - var pexpr = (PrimitiveExpression)expr.Node; - if (!(pexpr.Value is string || pexpr.Value is char) && !pexpr.LiteralValue.Contains('.')) { - return null; - } - } - - resolveResult = ResolveExpression(expr); - if (resolveResult == null) { - return null; - } - if (expr.Node is AstType) { - return CreateTypeAndNamespaceCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2); - } - return CreateCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2); + return HandleMemberReferenceCompletion(GetExpressionBeforeCursor()); case '#': if (IsInsideCommentOrString()) { return null; @@ -506,25 +510,32 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var contextList = new CompletionDataWrapper (this); var identifierStart = GetExpressionAtCursor(); + if (identifierStart != null) { - if (identifierStart != null && identifierStart.Node is TypeParameterDeclaration) { - return null; - } - - if (identifierStart != null && identifierStart.Node is Identifier) { - // May happen in variable names - return controlSpace ? DefaultControlSpaceItems(identifierStart) : null; - } + + if (identifierStart.Node is TypeParameterDeclaration) { + return null; + } - if (identifierStart != null && identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) { - return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null; - } + if (identifierStart.Node is MemberReferenceExpression) { + return HandleMemberReferenceCompletion(new ExpressionResult (((MemberReferenceExpression)identifierStart.Node).Target, identifierStart.Unit)); + } - if (identifierStart != null && identifierStart.Node is CatchClause) { - if (((CatchClause)identifierStart.Node).VariableNameToken.Contains(location)) { - return null; + if (identifierStart.Node is Identifier) { + // May happen in variable names + return controlSpace ? DefaultControlSpaceItems(identifierStart) : null; + } + + if (identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) { + return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null; + } + + if (identifierStart.Node is CatchClause) { + if (((CatchClause)identifierStart.Node).VariableNameToken.Contains(location)) { + return null; + } + identifierStart = null; } - identifierStart = null; } if (!(char.IsLetter(completionChar) || completionChar == '_') && (!controlSpace || identifierStart == null || !(identifierStart.Node.Parent is ArrayInitializerExpression))) { return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs index 6b80734c51..f9f5b2c25c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs @@ -4789,5 +4789,27 @@ class B : A Assert.AreEqual (2, provider.Data.Where (d => d.DisplayText == "Method").Count ()); } + /// + /// Bug 3973 - code completion forgets context if text is deleted + /// + [Test()] + public void TestBug3973 () + { + var provider = CreateProvider ( +@" +using System; + +class A +{ + public static void Main (string[] args) + { + Console.$W$ + } +} + +"); + Assert.IsNotNull (provider.Find ("WriteLine"), "'WriteLine' not found."); + } + } }