提交 d443394a 编写于 作者: C CyrusNajmabadi

Flesh out more of package installation.

上级 414a6784
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.AddPackage;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Packaging;
......@@ -15,7 +15,7 @@
namespace Microsoft.CodeAnalysis.AddMissingReference
{
internal abstract class AbstractAddMissingReferenceCodeFixProvider<TIdentifierNameSyntax> : CodeFixProvider
internal abstract partial class AbstractAddMissingReferenceCodeFixProvider<TIdentifierNameSyntax> : CodeFixProvider
where TIdentifierNameSyntax : SyntaxNode
{
private readonly IPackageInstallerService _packageInstallerService;
......@@ -61,7 +61,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var searchNugetPackages = options.GetOption(
SymbolSearchOptions.SuggestForTypesInNuGetPackages, language);
var builder = ArrayBuilder<CodeAction>.GetInstance();
var codeActions = ArrayBuilder<CodeAction>.GetInstance();
if (symbolSearchService != null &&
installerService != null &&
searchNugetPackages &&
......@@ -70,24 +70,50 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
foreach (var packageSource in installerService.PackageSources)
{
cancellationToken.ThrowIfCancellationRequested();
await AddPackagesCodeActionsAsync(
var sortedPackages = await FindMatchingPackagesAsync(
packageSource, symbolSearchService, installerService,
uniqueIdentities, builder, cancellationToken).ConfigureAwait(false);
uniqueIdentities, codeActions, cancellationToken).ConfigureAwait(false);
foreach (var package in sortedPackages)
{
var installedVersions = installerService.GetInstalledVersions(package.PackageName);
foreach (var version in installedVersions)
{
codeActions.Add(new InstallPackageCodeAction(
installerService, document, packageSource.Source,
package.PackageName, version, isLocal: true));
}
}
}
}
return builder.ToImmutableAndFree();
return codeActions.ToImmutableAndFree();
}
private Task AddPackagesCodeActionsAsync(
PackageSource packageSource,
ISymbolSearchService symbolSearchService,
private async Task<ImmutableArray<PackageWithAssemblyResult>> FindMatchingPackagesAsync(
PackageSource source,
ISymbolSearchService searchService,
IPackageInstallerService installerService,
ISet<AssemblyIdentity> uniqueIdentities,
ArrayBuilder<CodeAction> builder,
CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyTask;
cancellationToken.ThrowIfCancellationRequested();
var result = new HashSet<PackageWithAssemblyResult>();
foreach (var identity in uniqueIdentities)
{
var packagesWithAssembly = await searchService.FindPackagesWithAssemblyAsync(
source.Name, identity.Name, cancellationToken).ConfigureAwait(false);
result.AddRange(packagesWithAssembly);
}
// Ensure the packages are sorted by rank.
var sortedPackages = result.ToImmutableArray().Sort();
return sortedPackages;
}
private static async Task<ImmutableArray<CodeAction>> GetAddReferencesCodeActionsAsync(CodeFixContext context, ISet<AssemblyIdentity> uniqueIdentities)
......@@ -182,6 +208,7 @@ private static IEnumerable<ITypeSymbol> GetTypesFromSymbol(ISymbol symbol)
yield return propertySymbol.Type;
}
yield return symbol?.GetContainingTypeOrThis();
}
}
......@@ -212,4 +239,4 @@ private static AssemblyIdentity GetAssemblyIdentity(IEnumerable<ITypeSymbol> typ
return null;
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.Shared.Utilities;
namespace Microsoft.CodeAnalysis.AddPackage
{
internal class InstallPackageCodeAction : CodeAction
{
private readonly CodeActionOperation _installPackageOperation;
public override string Title => _installPackageOperation.Title;
public InstallPackageCodeAction(
IPackageInstallerService installerService,
Document document,
string source,
string packageName,
string versionOpt,
bool isLocal)
{
_installPackageOperation = new InstallPackageCodeActionOperation(
installerService, document, source, packageName, versionOpt, isLocal);
}
internal override Task<ImmutableArray<CodeActionOperation>> ComputeOperationsAsync(
IProgressTracker progressTracker, CancellationToken cancellationToken)
{
return Task.FromResult(ImmutableArray.Create(_installPackageOperation));
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Threading;
......@@ -24,12 +25,12 @@ internal abstract class FixSomeCodeAction : CodeAction
_showPreviewChangesDialog = showPreviewChangesDialog;
}
protected override Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(CancellationToken cancellationToken)
protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(CancellationToken cancellationToken)
{
return ComputeOperationsAsync(new ProgressTracker(), cancellationToken);
return await ComputeOperationsAsync(new ProgressTracker(), cancellationToken).ConfigureAwait(false);
}
internal override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(
internal override Task<ImmutableArray<CodeActionOperation>> ComputeOperationsAsync(
IProgressTracker progressTracker, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
......@@ -38,9 +39,9 @@ protected override Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync
var service = FixAllState.Project.Solution.Workspace.Services.GetService<IFixAllGetFixesService>();
// Use the new cancellation token instead of the stale one present inside _fixAllContext.
return await service.GetFixAllOperationsAsync(
return service.GetFixAllOperationsAsync(
FixAllState.CreateFixAllContext(progressTracker, cancellationToken),
_showPreviewChangesDialog).ConfigureAwait(false);
_showPreviewChangesDialog);
}
internal async override Task<Solution> GetChangedSolutionAsync(
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Host;
......@@ -13,7 +14,7 @@ internal interface IFixAllGetFixesService : IWorkspaceService
/// Computes the fix all occurrences code fix, brings up the preview changes dialog for the fix and
/// returns the code action operations corresponding to the fix.
/// </summary>
Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(FixAllContext fixAllContext, bool showPreviewChangesDialog);
Task<ImmutableArray<CodeActionOperation>> GetFixAllOperationsAsync(FixAllContext fixAllContext, bool showPreviewChangesDialog);
/// <summary>
/// Computes the fix all occurrences code fix and returns the changed solution.
......
......@@ -101,9 +101,10 @@
<DependentUpon>FeaturesResources.resx</DependentUpon>
</Compile>
<Compile Include="CodeFixes\FixAllOccurrences\FixSomeCodeAction.cs" />
<Compile Include="AddPackage\InstallPackageCodeAction.cs" />
<Compile Include="NavigateTo\AbstractNavigateToSearchService.SearchResult.cs" />
<Compile Include="AddMissingReference\AbstractAddMissingReferenceCodeFixProvider.cs" />
<Compile Include="AddMissingReference\CodeAction.cs" />
<Compile Include="AddMissingReference\AddMissingReferenceCodeAction.cs" />
<Compile Include="NavigateTo\AbstractNavigateToSearchService.Remote.cs" />
<Compile Include="NavigateTo\AbstractNavigateToSearchService.InProcess.cs" />
<Compile Include="NavigateTo\IRemoteNavigateToSearchService.cs" />
......
......@@ -117,10 +117,11 @@ protected virtual async Task<IEnumerable<CodeActionOperation>> ComputeOperations
return new CodeActionOperation[] { new ApplyChangesOperation(changedSolution) };
}
internal virtual Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(
internal virtual async Task<ImmutableArray<CodeActionOperation>> ComputeOperationsAsync(
IProgressTracker progressTracker, CancellationToken cancellationToken)
{
return ComputeOperationsAsync(cancellationToken);
var operations = await ComputeOperationsAsync(cancellationToken).ConfigureAwait(false);
return operations.ToImmutableArray();
}
/// <summary>
......
......@@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Host;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Packaging
{
......@@ -16,7 +17,7 @@ internal interface IPackageInstallerService : IWorkspaceService
bool TryInstallPackage(Workspace workspace, DocumentId documentId, string source, string packageName, string versionOpt, CancellationToken cancellationToken);
IEnumerable<string> GetInstalledVersions(string packageName);
ImmutableArray<string> GetInstalledVersions(string packageName);
IEnumerable<Project> GetProjectsWithInstalledPackage(Solution solution, string packageName, string version);
......@@ -26,15 +27,24 @@ internal interface IPackageInstallerService : IWorkspaceService
event EventHandler PackageSourcesChanged;
}
internal struct PackageSource
internal struct PackageSource : IEquatable<PackageSource>
{
public readonly string Name;
public readonly string Source;
public PackageSource(string name, string source)
{
this.Name = name;
this.Source = source;
Name = name;
Source = source;
}
public override bool Equals(object obj)
=> Equals((PackageSource)obj);
public bool Equals(PackageSource other)
=> Name == other.Name && Source == other.Source;
public override int GetHashCode()
=> Hash.Combine(Name, Source.GetHashCode());
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
......@@ -25,6 +26,17 @@ internal interface ISymbolSearchService : IWorkspaceService
Task<ImmutableArray<PackageWithTypeResult>> FindPackagesWithTypeAsync(
string source, string name, int arity, CancellationToken cancellationToken);
/// <summary>
/// Searches for packages that contain an assembly with the provided name.
/// Note: Implementations are free to return the results they feel best for the
/// given data. Specifically, they can do exact or fuzzy matching on the name.
///
/// Implementations should return results in order from best to worst (from their
/// perspective).
/// </summary>
Task<ImmutableArray<PackageWithAssemblyResult>> FindPackagesWithAssemblyAsync(
string source, string assemblyName, CancellationToken cancellationToken);
/// <summary>
/// Searches for reference assemblies that contain a type with the provided name and arity.
/// Note: Implementations are free to return the results they feel best for the
......@@ -62,6 +74,44 @@ internal class PackageWithTypeResult
}
}
internal class PackageWithAssemblyResult : IEquatable<PackageWithAssemblyResult>, IComparable<PackageWithAssemblyResult>
{
public readonly string PackageName;
public readonly string Version;
internal readonly int Rank;
public PackageWithAssemblyResult(
string packageName,
string version,
int rank)
{
PackageName = packageName;
Version = string.IsNullOrWhiteSpace(version) ? null : version;
Rank = rank;
}
public override int GetHashCode()
=> PackageName.GetHashCode();
public override bool Equals(object obj)
=> Equals((PackageWithAssemblyResult)obj);
public bool Equals(PackageWithAssemblyResult other)
=> PackageName.Equals(other.PackageName);
public int CompareTo(PackageWithAssemblyResult other)
{
var diff = Rank - other.Rank;
if (diff != 0)
{
return -diff;
}
return PackageName.CompareTo(other.PackageName);
}
}
internal class ReferenceAssemblyWithTypeResult
{
public readonly IReadOnlyList<string> ContainingNamespaceNames;
......@@ -88,6 +138,12 @@ internal class DefaultSymbolSearchService : ISymbolSearchService
return SpecializedTasks.EmptyImmutableArray<PackageWithTypeResult>();
}
public Task<ImmutableArray<PackageWithAssemblyResult>> FindPackagesWithAssemblyAsync(
string source, string assemblyName, CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyImmutableArray<PackageWithAssemblyResult>();
}
public Task<ImmutableArray<ReferenceAssemblyWithTypeResult>> FindReferenceAssembliesWithTypeAsync(
string name, int arity, CancellationToken cancellationToken)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册