From 3b682d43b1a25e160f4678bf37345f74a6221484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Wed, 15 Feb 2012 10:16:59 +0100 Subject: [PATCH] Fixed code completion bug. --- .../Completion/CSharpCompletionEngineBase.cs | 81 +++++++++++++------ .../CodeCompletion/CodeCompletionBugTests.cs | 30 +++++++ 2 files changed, 87 insertions(+), 24 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs index 203a4a8eda..267fdb4b7e 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs @@ -225,48 +225,80 @@ namespace ICSharpCode.NRefactory.CSharp.Completion { var bracketStack = new Stack> (); - bool isInString = false, isInChar = false; - bool isInLineComment = false, isInBlockComment = false; + bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false; - for (int pos = 0; pos < memberText.Length; pos++) { - char ch = memberText [pos]; + for (int i = 0; i < memberText.Length; i++) { + char ch = memberText [i]; + char nextCh = i + 1 < memberText.Length ? memberText [i + 1] : '\0'; switch (ch) { case '(': case '[': case '{': - if (!isInString && !isInChar && !isInLineComment && !isInBlockComment) - bracketStack.Push (Tuple.Create (ch, pos)); + if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) + break; + bracketStack.Push (Tuple.Create (ch, i)); break; case ')': case ']': case '}': - if (!isInString && !isInChar && !isInLineComment && !isInBlockComment) + if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) + break; if (bracketStack.Count > 0) bracketStack.Pop (); break; - case '\r': - case '\n': - isInLineComment = false; - break; case '/': - if (isInBlockComment) { - if (pos > 0 && memberText [pos - 1] == '*') - isInBlockComment = false; - } else if (!isInString && !isInChar && pos + 1 < memberText.Length) { - char nextChar = memberText [pos + 1]; - if (nextChar == '/') - isInLineComment = true; - if (!isInLineComment && nextChar == '*') - isInBlockComment = true; + if (inString || inChar || inVerbatimString) + break; + if (nextCh == '/') { + i++; + inSingleComment = true; + } + if (nextCh == '*') + inMultiLineComment = true; + break; + case '*': + if (inString || inChar || inVerbatimString || inSingleComment) + break; + if (nextCh == '/') { + i++; + inMultiLineComment = false; } break; + case '@': + if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) + break; + if (nextCh == '"') { + i++; + inVerbatimString = true; + } + break; + case '\n': + case '\r': + inSingleComment = false; + inString = false; + inChar = false; + break; + case '\\': + if (inString || inChar) + i++; + break; case '"': - if (!(isInChar || isInLineComment || isInBlockComment)) - isInString = !isInString; + if (inSingleComment || inMultiLineComment || inChar) + break; + if (inVerbatimString) { + if (nextCh == '"') { + i++; + break; + } + inVerbatimString = false; + break; + } + inString = !inString; break; case '\'': - if (!(isInString || isInLineComment || isInBlockComment)) - isInChar = !isInChar; + if (inSingleComment || inMultiLineComment || inString || inVerbatimString) + break; + inChar = !inChar; break; default : break; @@ -369,6 +401,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } else { memberLocation = new TextLocation (1, 1); } + using (var stream = new System.IO.StringReader (wrapper.ToString ())) { try { var parser = new CSharpParser (); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs index 307fff44c8..6bb78986e6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs @@ -1961,6 +1961,36 @@ class Test Assert.IsNotNull (provider.Find ("Test"), "method 'Test' not found"); } + /// + /// Bug 3438 - [New Resolver] Local var missing in code completion + /// + [Test()] + public void Test3438 () + { + CombinedProviderTest ( +@" +using System; +using System.Text; + +class C +{ + void GetElementXml (int indent) + { + StringBuilder sb = new StringBuilder (); + if (indent == 0) + sb.Append ("" xmlns:android=\""http://schemas.android.com/apk/res/android\""""); + + if (indent != 0) { + string data; + $d$ + } + } +}", provider => { + Assert.IsNotNull (provider.Find ("data"), "'data' not found."); + }); + } + + /// /// Bug 474199 - Code completion not working for a nested class ///