|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.InlineRename;
using Microsoft.CodeAnalysis.InlineRename;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Roslyn.VisualStudio.IntegrationTests;
using Roslyn.VisualStudio.IntegrationTests.InProcess;
using WindowsInput.Native;
using Xunit;
using Xunit.Sdk;
namespace Roslyn.VisualStudio.NewIntegrationTests.VisualBasic
{
[Trait(Traits.Feature, Traits.Features.Rename)]
public class BasicRename : AbstractEditorTest
{
protected override string LanguageName => LanguageNames.VisualBasic;
public BasicRename()
: base(nameof(BasicRename))
{
}
public override async Task InitializeAsync()
{
await base.InitializeAsync();
// reset relevant global options to default values:
var globalOptions = await TestServices.Shell.GetComponentModelServiceAsync<IGlobalOptionService>(HangMitigatingCancellationToken);
globalOptions.SetGlobalOption(InlineRenameUIOptionsStorage.UseInlineAdornment, false);
globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.RenameInComments, false);
globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.RenameInStrings, false);
globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.RenameOverloads, false);
globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.RenameFile, true);
globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.PreviewChanges, false);
}
[IdeFact]
public async Task VerifyLocalVariableRename()
{
var markup = @"
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
Dim [|x|]$$ As Integer = 0
[|x|] = 5
TestMethod([|x|])
End Sub
Sub TestMethod(y As Integer)
End Sub
End Module";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync(new InputKey[] { VirtualKeyCode.VK_Y, VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
Dim y$$ As Integer = 0
y = 5
TestMethod(y)
End Sub
Sub TestMethod(y As Integer)
End Sub
End Module", HangMitigatingCancellationToken);
}
[IdeFact]
public async Task VerifyLocalVariableRenameWithCommentsUpdated()
{
// "variable" is intentionally misspelled as "varixable" and "this" is misspelled as
// "thix" below to ensure we don't change instances of "x" in comments that are part of
// larger words
var markup = @"
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Program
''' <summary>
''' creates a varixable named [|x|] xx
''' </summary>
''' <param name=""args""></param>
Sub Main(args As String())
' thix varixable is named [|x|] xx
Dim [|x|]$$ As Integer = 0
[|x|] = 5
TestMethod([|x|])
End Module";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
await TestServices.InlineRename.ToggleIncludeCommentsAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync(new InputKey[] { VirtualKeyCode.VK_Y, VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Program
''' <summary>
''' creates a varixable named y xx
''' </summary>
''' <param name=""args""></param>
Sub Main(args As String())
' thix varixable is named y xx
Dim y$$ As Integer = 0
y = 5
TestMethod(y)
End Module", HangMitigatingCancellationToken);
}
[IdeFact]
public async Task VerifyLocalVariableRenameWithStringsUpdated()
{
var markup = @"
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
Dim [|x|]$$ As Integer = 0
[|x|] = 5
Dim s = ""[|x|] xx [|x|]""
End Sub
End Module";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
await TestServices.InlineRename.ToggleIncludeStringsAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync(new InputKey[] { VirtualKeyCode.VK_Y, VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
Dim y$$ As Integer = 0
y = 5
Dim s = ""y xx y""
End Sub
End Module", HangMitigatingCancellationToken);
}
[IdeFact]
public async Task VerifyOverloadsUpdated()
{
var markup = @"
Interface I
Sub [|TestMethod|]$$(y As Integer)
Sub [|TestMethod|](y As String)
End Interface
Public MustInherit Class A
Implements I
Public MustOverride Sub [|TestMethod|](y As Integer) Implements I.[|TestMethod|]
Public MustOverride Sub [|TestMethod|](y As String) Implements I.[|TestMethod|]
End Class";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
await TestServices.InlineRename.ToggleIncludeOverloadsAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync(new InputKey[] { VirtualKeyCode.VK_Y, VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Interface I
Sub y$$(y As Integer)
Sub y(y As String)
End Interface
Public MustInherit Class A
Implements I
Public MustOverride Sub y(y As Integer) Implements I.y
Public MustOverride Sub y(y As String) Implements I.y
End Class", HangMitigatingCancellationToken);
}
[IdeFact, WorkItem("https://github.com/dotnet/roslyn/issues/21657")]
public async Task VerifyAttributeRename()
{
var markup = @"
Imports System
Public Class [|$$ustom|]Attribute
Inherits Attribute
End Class";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync(new InputKey[] { "Custom", VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Public Class Custom$$Attribute
Inherits Attribute
End Class", HangMitigatingCancellationToken);
}
[IdeFact, WorkItem("https://github.com/dotnet/roslyn/issues/21657")]
public async Task VerifyAttributeRenameWhileRenameClasss()
{
var markup = @"
Imports System
Public Class [|$$ustom|]Attribute
Inherits Attribute
End Class";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync("Custom", HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Public Class Custom$$Attribute
Inherits Attribute
End Class", HangMitigatingCancellationToken);
}
[IdeFact, WorkItem("https://github.com/dotnet/roslyn/issues/21657")]
public async Task VerifyAttributeRenameWhileRenameAttribute()
{
var markup = @"
Imports System
<[|$$ustom|]>
Class Bar
End Class
Public Class [|ustom|]Attribute
Inherits Attribute
End Class";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync("Custom", HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
<Custom$$>
Class Bar
End Class
Public Class CustomAttribute
Inherits Attribute
End Class", HangMitigatingCancellationToken);
}
[IdeFact, WorkItem("https://github.com/dotnet/roslyn/issues/21657")]
public async Task VerifyAttributeRenameWhileRenameAttributeClass()
{
var markup = @"
Imports System
<[|ustom|]>
Class Bar
End Class
Public Class [|$$ustom|]Attribute
Inherits Attribute
End Class";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync("Custom", HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
<Custom>
Class Bar
End Class
Public Class Custom$$Attribute
Inherits Attribute
End Class", HangMitigatingCancellationToken);
}
[IdeFact, WorkItem("https://github.com/dotnet/roslyn/issues/21657")]
public async Task VerifyAttributeCapitalizedRename()
{
var markup = @"
Imports System
Public Class [|$$ustom|]ATTRIBUTE
Inherits Attribute
End Class";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync(new InputKey[] { "Custom", VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Public Class CustomAttribute$$
Inherits Attribute
End Class", HangMitigatingCancellationToken);
}
[IdeFact, WorkItem("https://github.com/dotnet/roslyn/issues/21657")]
public async Task VerifyAttributeNotCapitalizedRename()
{
var markup = @"
Imports System
Public Class [|$$ustom|]attribute
Inherits Attribute
End Class";
await SetUpEditorAsync(markup, HangMitigatingCancellationToken);
await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken);
MarkupTestFile.GetSpans(markup, out var _, out ImmutableArray<TextSpan> renameSpans);
var tags = await TestServices.Editor.GetRenameTagsAsync(HangMitigatingCancellationToken);
var tagSpans = tags.SelectAsArray(tag => new TextSpan(tag.Span.Start, tag.Span.Length));
AssertEx.SetEqual(renameSpans, tagSpans);
await TestServices.Input.SendWithoutActivateAsync(new InputKey[] { "Custom", VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken);
try
{
// This is the expected behavior
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Public Class CustomAttribute$$
Inherits Attribute
End Class", HangMitigatingCancellationToken);
}
catch (XunitException)
{
// But sometimes we get this instead
await TestServices.EditorVerifier.TextEqualsAsync(@"
Imports System
Public Class CustomA$$ttribute
Inherits Attribute
End Class", HangMitigatingCancellationToken);
}
}
}
}
|