|
// 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.
#nullable disable
using System;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.AddImport;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.SymbolSearch;
using Microsoft.CodeAnalysis.Test.Utilities;
using Moq;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddUsing;
using FixProviderData = Tuple<IPackageInstallerService, ISymbolSearchService>;
[Trait(Traits.Feature, Traits.Features.CodeActionsAddImport)]
public class AddUsingNuGetTests : AbstractAddUsingTests
{
private static readonly ImmutableArray<PackageSource> NugetPackageSources =
ImmutableArray.Create(new PackageSource(PackageSourceHelper.NugetOrgSourceName, "http://nuget.org/"));
protected override void InitializeWorkspace(EditorTestWorkspace workspace, TestParameters parameters)
{
workspace.GlobalOptions.SetGlobalOption(SymbolSearchOptionsStorage.SearchNuGetPackages, LanguageNames.CSharp, true);
workspace.GlobalOptions.SetGlobalOption(SymbolSearchOptionsStorage.SearchReferenceAssemblies, LanguageNames.CSharp, true);
}
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(
Workspace workspace, TestParameters parameters)
{
var data = (FixProviderData)parameters.fixProviderData;
return (null, new CSharpAddImportCodeFixProvider(data.Item1, data.Item2));
}
protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> actions)
=> FlattenActions(actions);
[Fact]
public async Task TestSearchPackageCustomFeedName()
{
var packageSources = ImmutableArray.Create(new PackageSource("My Custom Nuget Feed", "http://nuget.org/"));
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray<string>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(packageSources);
installerServiceMock.Setup(s => s.TryInstallPackageAsync(It.IsAny<Workspace>(), It.IsAny<DocumentId>(), It.IsAny<string>(), "NuGetPackage", It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IProgress<CodeAnalysisProgress>>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true));
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(
PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NuGetNamespace")));
await TestInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}",
@"using NuGetNamespace;
class C
{
NuGetType n;
}", fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object));
}
[Fact]
public async Task TestSearchPackageFakeNugetFeed()
{
var packageSources = ImmutableArray.Create(new PackageSource("nuget.org", "http://fakenuget.org/"));
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray<string>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(packageSources);
installerServiceMock.Setup(s => s.TryInstallPackageAsync(It.IsAny<Workspace>(), It.IsAny<DocumentId>(), It.IsAny<string>(), "NuGetPackage", It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IProgress<CodeAnalysisProgress>>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true));
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(
"nuget.org", "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NuGetNamespace")));
await TestInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}",
@"using NuGetNamespace;
class C
{
NuGetType n;
}", fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object));
}
[Fact]
public async Task TestSearchPackageSingleName()
{
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray<string>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.TryInstallPackageAsync(It.IsAny<Workspace>(), It.IsAny<DocumentId>(), It.IsAny<string>(), "NuGetPackage", It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IProgress<CodeAnalysisProgress>>(), It.IsAny<CancellationToken>()))
.Returns(SpecializedTasks.True);
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(
PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NuGetNamespace")));
await TestInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}",
@"using NuGetNamespace;
class C
{
NuGetType n;
}", fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object));
}
[Fact]
public async Task TestSearchPackageMultipleNames()
{
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray<string>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.TryInstallPackageAsync(It.IsAny<Workspace>(), It.IsAny<DocumentId>(), It.IsAny<string>(), "NuGetPackage", It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<IProgress<CodeAnalysisProgress>>(), It.IsAny<CancellationToken>()))
.Returns(SpecializedTasks.True);
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(
PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NS1", "NS2")));
await TestInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}",
@"using NS1.NS2;
class C
{
NuGetType n;
}", fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object));
}
[Fact]
public async Task TestMissingIfPackageAlreadyInstalled()
{
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage"))
.Returns(true);
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(
PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NS1", "NS2")));
await TestMissingInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}", new TestParameters(fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object)));
}
[Fact]
public async Task TestOptionsOffered()
{
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetProjectsWithInstalledPackage(It.IsAny<Solution>(), "NuGetPackage", "1.0")).Returns(ImmutableArray<Project>.Empty);
installerServiceMock.Setup(i => i.GetProjectsWithInstalledPackage(It.IsAny<Solution>(), "NuGetPackage", "2.0")).Returns(ImmutableArray<Project>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.GetInstalledVersions("NuGetPackage"))
.Returns(ImmutableArray.Create("1.0", "2.0"));
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(
PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NS1", "NS2")));
var data = new FixProviderData(installerServiceMock.Object, packageServiceMock.Object);
await TestSmartTagTextAsync(
@"class C
{
[|NuGetType|] n;
}",
string.Format(FeaturesResources.Use_local_version_0, "1.0"),
parameters: new TestParameters(fixProviderData: data));
await TestSmartTagTextAsync(
@"class C
{
[|NuGetType|] n;
}",
string.Format(FeaturesResources.Use_local_version_0, "2.0"),
parameters: new TestParameters(index: 1, fixProviderData: data));
await TestSmartTagTextAsync(
@"class C
{
[|NuGetType|] n;
}",
FeaturesResources.Find_and_install_latest_version,
parameters: new TestParameters(index: 2, fixProviderData: data));
}
[Fact]
public async Task TestInstallGetsCalledNoVersion()
{
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray<string>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.TryInstallPackageAsync(It.IsAny<Workspace>(), It.IsAny<DocumentId>(), It.IsAny<string>(), "NuGetPackage", /*versionOpt*/ null, It.IsAny<bool>(), It.IsAny<IProgress<CodeAnalysisProgress>>(), It.IsAny<CancellationToken>()))
.Returns(SpecializedTasks.True);
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(
PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NuGetNamespace")));
await TestInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}",
@"using NuGetNamespace;
class C
{
NuGetType n;
}", fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object));
installerServiceMock.Verify();
}
[Fact]
public async Task TestInstallGetsCalledWithVersion()
{
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetProjectsWithInstalledPackage(It.IsAny<Solution>(), "NuGetPackage", "1.0")).Returns(ImmutableArray<Project>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.GetInstalledVersions("NuGetPackage"))
.Returns(ImmutableArray.Create("1.0"));
installerServiceMock.Setup(s => s.TryInstallPackageAsync(It.IsAny<Workspace>(), It.IsAny<DocumentId>(), It.IsAny<string>(), "NuGetPackage", "1.0", It.IsAny<bool>(), It.IsAny<IProgress<CodeAnalysisProgress>>(), It.IsAny<CancellationToken>()))
.Returns(SpecializedTasks.True);
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NuGetNamespace")));
await TestInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}",
@"using NuGetNamespace;
class C
{
NuGetType n;
}", fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object));
installerServiceMock.Verify();
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/pull/14516")]
public async Task TestFailedInstallRollsBackFile()
{
var installerServiceMock = new Mock<IPackageInstallerService>(MockBehavior.Strict);
installerServiceMock.Setup(i => i.IsEnabled(It.IsAny<ProjectId>())).Returns(true);
installerServiceMock.Setup(i => i.IsInstalled(It.IsAny<ProjectId>(), "NuGetPackage")).Returns(false);
installerServiceMock.Setup(i => i.GetProjectsWithInstalledPackage(It.IsAny<Solution>(), "NuGetPackage", "1.0")).Returns(ImmutableArray<Project>.Empty);
installerServiceMock.Setup(i => i.TryGetPackageSources()).Returns(NugetPackageSources);
installerServiceMock.Setup(s => s.GetInstalledVersions("NuGetPackage"))
.Returns(ImmutableArray.Create("1.0"));
installerServiceMock.Setup(s => s.TryInstallPackageAsync(It.IsAny<Workspace>(), It.IsAny<DocumentId>(), It.IsAny<string>(), "NuGetPackage", "1.0", It.IsAny<bool>(), It.IsAny<IProgress<CodeAnalysisProgress>>(), It.IsAny<CancellationToken>()))
.Returns(SpecializedTasks.False);
var packageServiceMock = new Mock<ISymbolSearchService>(MockBehavior.Strict);
packageServiceMock.Setup(s => s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => ValueTaskFactory.FromResult(ImmutableArray<ReferenceAssemblyWithTypeResult>.Empty));
packageServiceMock.Setup(s => s.FindPackagesWithTypeAsync(PackageSourceHelper.NugetOrgSourceName, "NuGetType", 0, It.IsAny<CancellationToken>()))
.Returns(() => CreateSearchResult("NuGetPackage", "NuGetType", CreateNameParts("NuGetNamespace")));
await TestInRegularAndScriptAsync(
@"class C
{
[|NuGetType|] n;
}",
@"class C
{
NuGetType n;
}", fixProviderData: new FixProviderData(installerServiceMock.Object, packageServiceMock.Object));
installerServiceMock.Verify();
}
private static ValueTask<ImmutableArray<PackageWithTypeResult>> CreateSearchResult(
string packageName, string typeName, ImmutableArray<string> containingNamespaceNames)
{
return CreateSearchResult(new PackageWithTypeResult(
packageName: packageName, rank: 0, typeName: typeName,
version: null, containingNamespaceNames: containingNamespaceNames));
}
private static ValueTask<ImmutableArray<PackageWithTypeResult>> CreateSearchResult(params PackageWithTypeResult[] results)
=> new(ImmutableArray.Create(results));
private static ImmutableArray<string> CreateNameParts(params string[] parts)
=> parts.ToImmutableArray();
}
|