diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_Regex.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_Regex.vb index 1756e0aad120d..90f5bb8416d67 100644 --- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_Regex.vb +++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_Regex.vb @@ -6,7 +6,6 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense <[UseExportProvider]> Public Class CSharpCompletionCommandHandlerTests_Regex - Public Async Function ExplicitInvoke(showCompletionInArgumentLists As Boolean) As Task Using state = TestStateFactory.CreateCSharpTestState( @@ -29,6 +28,28 @@ class c End Using End Function + + Public Async Function ExplicitInvoke_Utf8(showCompletionInArgumentLists As Boolean) As Task + Using state = TestStateFactory.CreateCSharpTestState( + , showCompletionInArgumentLists:=showCompletionInArgumentLists) + + state.SendInvokeCompletionList() + Await state.AssertSelectedCompletionItem("\A", inlineDescription:=FeaturesResources.Regex_start_of_string_only_short) + state.SendTab() + Await state.AssertNoCompletionSession() + Assert.Contains("new Regex(""\\A""u8)", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) + End Using + End Function + Public Async Function ExplicitInvoke_VerbatimString(showCompletionInArgumentLists As Boolean) As Task Using state = TestStateFactory.CreateCSharpTestState( @@ -51,6 +72,74 @@ class c End Using End Function + + Public Async Function ExplicitInvoke_VerbatimUtf8String(showCompletionInArgumentLists As Boolean) As Task + Using state = TestStateFactory.CreateCSharpTestState( + , showCompletionInArgumentLists:=showCompletionInArgumentLists) + + state.SendInvokeCompletionList() + Await state.AssertSelectedCompletionItem("\A") + state.SendTab() + Await state.AssertNoCompletionSession() + Assert.Contains("new Regex(@""\A""u8)", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) + End Using + End Function + + + Public Async Function ExplicitInvoke_RawSingleLineString(showCompletionInArgumentLists As Boolean) As Task + Using state = TestStateFactory.CreateCSharpTestState( + , showCompletionInArgumentLists:=showCompletionInArgumentLists) + + state.SendInvokeCompletionList() + Await state.AssertSelectedCompletionItem("\A") + state.SendTab() + Await state.AssertNoCompletionSession() + Assert.Contains("new Regex(""""""\A """""")", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) + End Using + End Function + + + Public Async Function ExplicitInvoke_RawMultiLineString(showCompletionInArgumentLists As Boolean) As Task + Using state = TestStateFactory.CreateCSharpTestState( + , showCompletionInArgumentLists:=showCompletionInArgumentLists) + + state.SendInvokeCompletionList() + Await state.AssertSelectedCompletionItem("\A") + state.SendTab() + Await state.AssertNoCompletionSession() + Assert.Contains(" \A", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) + End Using + End Function + Public Async Function TestCaretPlacement(showCompletionInArgumentLists As Boolean) As Task Using state = TestStateFactory.CreateCSharpTestState( diff --git a/src/EditorFeatures/Test2/ReferenceHighlighting/CSharpReferenceHighlightingTests.vb b/src/EditorFeatures/Test2/ReferenceHighlighting/CSharpReferenceHighlightingTests.vb index 6c94879c8aa9a..fb51d56fc8a4d 100644 --- a/src/EditorFeatures/Test2/ReferenceHighlighting/CSharpReferenceHighlightingTests.vb +++ b/src/EditorFeatures/Test2/ReferenceHighlighting/CSharpReferenceHighlightingTests.vb @@ -8,8 +8,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting Public Class CSharpReferenceHighlightingTests Inherits AbstractReferenceHighlightingTests - - + Public Async Function TestVerifyNoHighlightsWhenOptionDisabled(testHost As TestHost) As Task Await VerifyHighlightsAsync( @@ -26,8 +25,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting optionIsEnabled:=False) End Function - - + Public Async Function TestVerifyHighlightsForClass(testHost As TestHost) As Task Await VerifyHighlightsAsync( @@ -41,8 +39,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting , testHost) End Function - - + Public Async Function TestVerifyHighlightsForScriptReference(testHost As TestHost) As Task Await VerifyHighlightsAsync( @@ -60,8 +57,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting , testHost) End Function - - + Public Async Function TestVerifyHighlightsForCSharpClassWithConstructor(testHost As TestHost) As Task Await VerifyHighlightsAsync( @@ -79,9 +75,8 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting , testHost) End Function + - - Public Async Function TestVerifyHighlightsForCSharpClassWithSynthesizedConstructor(testHost As TestHost) As Task Await VerifyHighlightsAsync( @@ -99,8 +94,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting , testHost) End Function - - + Public Async Function TestVerifyHighlightsOnCloseAngleOfGeneric(testHost As TestHost) As Task Await VerifyHighlightsAsync( @@ -123,8 +117,7 @@ class {|Definition:Program|} , testHost) End Function - - + Public Async Function TestVerifyNoHighlightsOnAsyncLambda(testHost As TestHost) As Task Await VerifyHighlightsAsync( @@ -149,9 +142,8 @@ class Program , testHost) End Function + - - Public Async Function TestAlias1(testHost As TestHost) As Task Dim input = @@ -175,9 +167,8 @@ namespace X Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestAlias2(testHost As TestHost) As Task Dim input = @@ -201,9 +192,8 @@ namespace X Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestAlias3(testHost As TestHost) As Task Dim input = @@ -227,9 +217,8 @@ namespace X Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestAlias4(testHost As TestHost) As Task Dim input = @@ -250,9 +239,8 @@ namespace N Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestHighlightThroughVar1(testHost As TestHost) As Task Dim input = @@ -275,9 +263,8 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestHighlightThroughVar2(testHost As TestHost) As Task Dim input = @@ -300,9 +287,8 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestHighlightThroughVar3(testHost As TestHost) As Task Dim input = @@ -327,9 +313,8 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestUsingAliasAndTypeWithSameName1(testHost As TestHost) As Task Dim input = @@ -344,9 +329,8 @@ class X { } Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestUsingAliasAndTypeWithSameName2(testHost As TestHost) As Task Dim input = @@ -361,9 +345,8 @@ class {|Definition:$$X|} { } Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestAccessor1(testHost As TestHost) As Task Dim input = @@ -390,9 +373,8 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestAccessor2(testHost As TestHost) As Task Dim input = @@ -440,9 +422,8 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestHighlightDynamicallyBoundMethod(testHost As TestHost) As Task Dim input = @@ -472,9 +453,8 @@ class A Await VerifyHighlightsAsync(input, testHost) End Function + - - Public Async Function TestHighlightParameterizedPropertyParameter(testHost As TestHost) As Task Dim input = @@ -497,8 +477,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestInterpolatedString1(testHost As TestHost) As Task Dim input = @@ -520,8 +499,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestInterpolatedString2(testHost As TestHost) As Task Dim input = @@ -543,8 +521,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestWrittenReference(testHost As TestHost) As Task Dim input = @@ -565,8 +542,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestWrittenReference2(testHost As TestHost) As Task Dim input = @@ -587,8 +563,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestPatternMatchingType1(testHost As TestHost) As Task Dim input = @@ -612,8 +587,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestPatternMatchingType2(testHost As TestHost) As Task Dim input = @@ -637,8 +611,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestPatternMatchingTypeScoping1(testHost As TestHost) As Task Dim input = @@ -669,8 +642,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestPatternMatchingTypeScoping2(testHost As TestHost) As Task Dim input = @@ -701,10 +673,8 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestRegexReference1(testHost As TestHost) As Task - Dim input = @@ -725,8 +695,57 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + + + Public Async Function TestRegexReference_RawStringInBounds(testHost As TestHost) As Task + Dim input = + + + +using System.Text.RegularExpressions; + +class C +{ + void Goo() + { + var r = new Regex(""" + {|Reference:(a)|}\0{|Reference:\$$1|} + """); + } +} + + + + + Await VerifyHighlightsAsync(input, testHost) + End Function + + + + Public Async Function TestRegexReference_RawStringOutOfBounds(testHost As TestHost) As Task + Dim input = + + + +using System.Text.RegularExpressions; + +class C +{ + void Goo() + { + var r = new Regex(""" + $$ (a)\0\1 + """); + } +} + + + + + Await VerifyHighlightsAsync(input, testHost) + End Function + + Public Async Function TestHighlightParamAndCommentsCursorOnDefinition(testHost As TestHost) As Task Dim input = @@ -753,8 +772,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestHighlightParamAndCommentsCursorOnReference(testHost As TestHost) As Task Dim input = @@ -781,8 +799,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestHighlightParamAndCommentsDefinitionNestedBetweenReferences(testHost As TestHost) As Task Dim input = @@ -809,8 +826,7 @@ class C Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestNotOnNewInObjectCreation(testHost As TestHost) As Task Dim input = @@ -834,8 +850,7 @@ namespace X Await VerifyHighlightsAsync(input, testHost) End Function - - + Public Async Function TestOnTypeInObjectCreation(testHost As TestHost) As Task Dim input = diff --git a/src/Features/CSharp/Portable/EmbeddedLanguages/EmbeddedLanguageUtilities.cs b/src/Features/CSharp/Portable/EmbeddedLanguages/EmbeddedLanguageUtilities.cs index e82e6a5995795..317e754a4970c 100644 --- a/src/Features/CSharp/Portable/EmbeddedLanguages/EmbeddedLanguageUtilities.cs +++ b/src/Features/CSharp/Portable/EmbeddedLanguages/EmbeddedLanguageUtilities.cs @@ -2,10 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - -using System.Diagnostics; using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.CSharp.Features.EmbeddedLanguages { @@ -18,21 +16,22 @@ internal static void AddComment(SyntaxEditor editor, SyntaxToken stringLiteral, SyntaxFactory.ElasticSpace); var newStringLiteral = stringLiteral.WithLeadingTrivia( stringLiteral.LeadingTrivia.AddRange(triviaList)); - editor.ReplaceNode(stringLiteral.Parent, stringLiteral.Parent.ReplaceToken(stringLiteral, newStringLiteral)); + var parent = stringLiteral.GetRequiredParent(); + editor.ReplaceNode( + parent, + parent.ReplaceToken(stringLiteral, newStringLiteral)); } public static string EscapeText(string text, SyntaxToken token) { - // This function is called when Completion needs to escape something its going to - // insert into the user's string token. This means that we only have to escape - // things that completion could insert. In this case, the only regex character - // that is relevant is the \ character, and it's only relevant if we insert into - // a normal string and not a verbatim string. There are no other regex characters - // that completion will produce that need any escaping. - Debug.Assert(token.Kind() == SyntaxKind.StringLiteralToken); - return token.IsVerbatimStringLiteral() - ? text - : text.Replace(@"\", @"\\"); + // This function is called when Completion needs to escape something its going to insert into the user's + // string token. This means that we only have to escape things that completion could insert. In this case, + // the only regex character that is relevant is the \ character, and it's only relevant if we insert into a + // normal string and not a verbatim string. There are no other regex characters that completion will + // produce that need any escaping. + return token.Kind() is SyntaxKind.StringLiteralToken or SyntaxKind.Utf8StringLiteralToken && !token.IsVerbatimStringLiteral() + ? text.Replace(@"\", @"\\") + : text; } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EmbeddedLanguages/VirtualChars/VirtualCharSequence.Chunks.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EmbeddedLanguages/VirtualChars/VirtualCharSequence.Chunks.cs index 1aba88e39213d..0db80681639a7 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EmbeddedLanguages/VirtualChars/VirtualCharSequence.Chunks.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EmbeddedLanguages/VirtualChars/VirtualCharSequence.Chunks.cs @@ -62,7 +62,12 @@ public ImmutableSegmentedListChunk(ImmutableSegmentedList array) return 0; }); - Debug.Assert(index >= 0); + + // Characters can be discontiguous (for example, in multi-line-raw-string literals). So if the + // position is in one of the gaps, it won't be able to find a corresponding virtual char. + if (index < 0) + return null; + return _array[index]; } }