提交 5731fe78 编写于 作者: C CyrusNajmabadi

Move the update engine portion of the SymbolSearch service down to the workspace layer.

上级 e78e8bc5
......@@ -34,8 +34,8 @@ protected override async Task<TestWorkspace> CreateWorkspaceFromFileAsync(string
{
var workspace = await base.CreateWorkspaceFromFileAsync(definition, parseOptions, compilationOptions);
workspace.Options = workspace.Options
.WithChangedOption(AddImportOptions.SuggestForTypesInNuGetPackages, LanguageNames.CSharp, true)
.WithChangedOption(AddImportOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.CSharp, true);
.WithChangedOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, LanguageNames.CSharp, true)
.WithChangedOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.CSharp, true);
return workspace;
}
......
......@@ -26,8 +26,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeActions.AddImp
Protected Overrides Async Function CreateWorkspaceFromFileAsync(definition As String, parseOptions As ParseOptions, compilationOptions As CompilationOptions) As Task(Of TestWorkspace)
Dim workspace = Await MyBase.CreateWorkspaceFromFileAsync(definition, parseOptions, compilationOptions)
workspace.Options = workspace.Options.
WithChangedOption(AddImportOptions.SuggestForTypesInNuGetPackages, LanguageNames.VisualBasic, True).
WithChangedOption(AddImportOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.VisualBasic, True)
WithChangedOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, LanguageNames.VisualBasic, True).
WithChangedOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.VisualBasic, True)
Return workspace
End Function
......
......@@ -266,9 +266,9 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
var options = workspaceServices.Workspace.Options;
var searchReferenceAssemblies = options.GetOption(
AddImportOptions.SuggestForTypesInReferenceAssemblies, language);
SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, language);
var searchNugetPackages = options.GetOption(
AddImportOptions.SuggestForTypesInNuGetPackages, language);
SymbolSearchOptions.SuggestForTypesInNuGetPackages, language);
if (symbolSearchService != null &&
searchReferenceAssemblies)
......
......@@ -372,13 +372,10 @@
<Compile Include="RemoveUnnecessaryImports\AbstractRemoveUnnecessaryImportsService.cs" />
<Compile Include="ReplaceMethodWithProperty\ReplaceMethodWithPropertyCodeRefactoringProvider.cs" />
<Compile Include="ReplaceMethodWithProperty\IReplaceMethodWithPropertyService.cs" />
<Compile Include="Shared\Options\AddImportOptionsProvider.cs" />
<Compile Include="Shared\Extensions\ProjectExtensions.cs" />
<Compile Include="Shared\Options\AddImportOptions.cs" />
<Compile Include="Shared\Options\ServiceComponentOnOffOptionsProvider.cs" />
<Compile Include="Shared\Options\ServiceFeatureOnOffOptions.cs" />
<Compile Include="Shared\Options\ServiceFeatureOnOffOptionsProvider.cs" />
<Compile Include="Shared\Utilities\IOUtilities.cs" />
<Compile Include="Shared\Utilities\LinkedFilesSymbolEquivalenceComparer.cs" />
<Compile Include="Shared\Utilities\SupportedPlatformData.cs" />
<Compile Include="Completion\Providers\SymbolCompletionItem.cs" />
......
......@@ -10,7 +10,5 @@ namespace Microsoft.CodeAnalysis.Shared.Options
internal static class ServiceComponentOnOffOptions
{
public static readonly Option<bool> DiagnosticProvider = new Option<bool>(nameof(ServiceComponentOnOffOptions), nameof(DiagnosticProvider), defaultValue: true);
public static readonly Option<bool> SymbolSearch = new Option<bool>(nameof(ServiceComponentOnOffOptions), nameof(SymbolSearch), defaultValue: true);
}
}
......@@ -12,8 +12,7 @@ namespace Microsoft.CodeAnalysis.Shared.Options
internal class ServiceComponentOnOffOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = ImmutableArray.Create(
ServiceComponentOnOffOptions.DiagnosticProvider,
ServiceComponentOnOffOptions.SymbolSearch);
ServiceComponentOnOffOptions.DiagnosticProvider);
public IEnumerable<IOption> GetOptions() => _options;
}
......
{
"dependencies": {
"System.Reflection": "4.1.0"
"System.Reflection": "4.1.0",
},
"frameworks": {
"netstandard1.3": {
......
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.CodeAnalysis.ExtractMethod;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.SymbolSearch;
using Microsoft.VisualStudio.LanguageServices.Implementation;
using Microsoft.VisualStudio.LanguageServices.Implementation.Options;
......@@ -19,8 +20,8 @@ public AdvancedOptionPageControl(IServiceProvider serviceProvider) : base(servic
InitializeComponent();
BindToOption(PlaceSystemNamespaceFirst, GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.CSharp);
BindToOption(SuggestForTypesInReferenceAssemblies, AddImportOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.CSharp);
BindToOption(SuggestForTypesInNuGetPackages, AddImportOptions.SuggestForTypesInNuGetPackages, LanguageNames.CSharp);
BindToOption(SuggestForTypesInReferenceAssemblies, SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.CSharp);
BindToOption(SuggestForTypesInNuGetPackages, SymbolSearchOptions.SuggestForTypesInNuGetPackages, LanguageNames.CSharp);
BindToOption(Split_string_literals_on_enter, SplitStringLiteralOptions.Enabled, LanguageNames.CSharp);
BindToOption(EnterOutliningMode, FeatureOnOffOptions.Outlining, LanguageNames.CSharp);
......
......@@ -15,6 +15,7 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.SymbolSearch;
namespace Microsoft.VisualStudio.LanguageServices.CSharp.Options
{
......@@ -359,14 +360,14 @@ public int SortUsings_PlaceSystemFirst
public int AddImport_SuggestForTypesInReferenceAssemblies
{
get { return GetBooleanOption(AddImportOptions.SuggestForTypesInReferenceAssemblies); }
set { SetBooleanOption(AddImportOptions.SuggestForTypesInReferenceAssemblies, value); }
get { return GetBooleanOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies); }
set { SetBooleanOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, value); }
}
public int AddImport_SuggestForTypesInNuGetPackages
{
get { return GetBooleanOption(AddImportOptions.SuggestForTypesInNuGetPackages); }
set { SetBooleanOption(AddImportOptions.SuggestForTypesInNuGetPackages, value); }
get { return GetBooleanOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages); }
set { SetBooleanOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, value); }
}
public int Space_AfterBasesColon
......
......@@ -15,6 +15,7 @@
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.SymbolSearch;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
......@@ -61,9 +62,9 @@ internal partial class PackageInstallerService : AbstractDelayStartedService, IP
public PackageInstallerService(
VisualStudioWorkspaceImpl workspace,
IVsEditorAdaptersFactoryService editorAdaptersFactoryService)
: base(workspace, ServiceComponentOnOffOptions.SymbolSearch,
AddImportOptions.SuggestForTypesInReferenceAssemblies,
AddImportOptions.SuggestForTypesInNuGetPackages)
: base(workspace, SymbolSearchOptions.Enabled,
SymbolSearchOptions.SuggestForTypesInReferenceAssemblies,
SymbolSearchOptions.SuggestForTypesInNuGetPackages)
{
_workspace = workspace;
_editorAdaptersFactoryService = editorAdaptersFactoryService;
......
......@@ -75,9 +75,9 @@ internal partial class SymbolSearchService : AbstractDelayStartedService, ISymbo
string localSettingsDirectory,
Func<Exception, bool> reportAndSwallowException,
CancellationTokenSource cancellationTokenSource)
: base(workspace, ServiceComponentOnOffOptions.SymbolSearch,
AddImportOptions.SuggestForTypesInReferenceAssemblies,
AddImportOptions.SuggestForTypesInNuGetPackages)
: base(workspace, SymbolSearchOptions.Enabled,
SymbolSearchOptions.SuggestForTypesInReferenceAssemblies,
SymbolSearchOptions.SuggestForTypesInNuGetPackages)
{
if (remoteControlService == null)
{
......
......@@ -5,6 +5,7 @@ Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Editor.Shared.Options
Imports Microsoft.CodeAnalysis.ExtractMethod
Imports Microsoft.CodeAnalysis.Shared.Options
Imports Microsoft.CodeAnalysis.SymbolSearch
Imports Microsoft.VisualStudio.LanguageServices.Implementation
Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
......@@ -15,8 +16,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
InitializeComponent()
BindToOption(PlaceSystemNamespaceFirst, GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.VisualBasic)
BindToOption(SuggestForTypesInReferenceAssemblies, AddImportOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.VisualBasic)
BindToOption(SuggestForTypesInNuGetPackages, AddImportOptions.SuggestForTypesInNuGetPackages, LanguageNames.VisualBasic)
BindToOption(SuggestForTypesInReferenceAssemblies, SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.VisualBasic)
BindToOption(SuggestForTypesInNuGetPackages, SymbolSearchOptions.SuggestForTypesInNuGetPackages, LanguageNames.VisualBasic)
BindToOption(EnableEndConstruct, FeatureOnOffOptions.EndConstruct, LanguageNames.VisualBasic)
BindToOption(EnableOutlining, FeatureOnOffOptions.Outlining, LanguageNames.VisualBasic)
......
......@@ -10,6 +10,7 @@ Imports Microsoft.CodeAnalysis.ExtractMethod
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Shared.Options
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.SymbolSearch
Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
<ComVisible(True)>
......@@ -207,19 +208,19 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Public Property Option_SuggestImportsForTypesInReferenceAssemblies As Boolean
Get
Return GetBooleanOption(AddImportOptions.SuggestForTypesInReferenceAssemblies)
Return GetBooleanOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies)
End Get
Set(value As Boolean)
SetBooleanOption(AddImportOptions.SuggestForTypesInReferenceAssemblies, value)
SetBooleanOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, value)
End Set
End Property
Public Property Option_SuggestImportsForTypesInNuGetPackages As Boolean
Get
Return GetBooleanOption(AddImportOptions.SuggestForTypesInNuGetPackages)
Return GetBooleanOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages)
End Get
Set(value As Boolean)
SetBooleanOption(AddImportOptions.SuggestForTypesInNuGetPackages, value)
SetBooleanOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, value)
End Set
End Property
......
// 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.IO;
using Microsoft.CodeAnalysis.Elfie.Model;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal partial class DefaultSymbolSearchUpdateEngine
{
private class DatabaseFactoryService : IDatabaseFactoryService
{
public AddReferenceDatabase CreateDatabaseFromBytes(byte[] bytes)
{
using (var memoryStream = new MemoryStream(bytes))
using (var streamReader = new StreamReader(memoryStream))
{
var database = new AddReferenceDatabase();
database.ReadText(streamReader);
return database;
}
}
}
}
}
// 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;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal partial class DefaultSymbolSearchUpdateEngine
{
private class DelayService : IDelayService
{
public TimeSpan CachePollDelay { get; } = TimeSpan.FromMinutes(1);
public TimeSpan FileWriteDelay { get; } = TimeSpan.FromSeconds(10);
public TimeSpan ExpectedFailureDelay { get; } = TimeSpan.FromMinutes(1);
public TimeSpan CatastrophicFailureDelay { get; } = TimeSpan.FromDays(1);
public TimeSpan UpdateSucceededDelay { get; } = TimeSpan.FromDays(1);
}
}
}
// 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.IO;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal partial class DefaultSymbolSearchUpdateEngine
{
private class IOService : IIOService
{
public void Create(DirectoryInfo directory) => directory.Create();
public void Delete(FileInfo file) => file.Delete();
public bool Exists(FileSystemInfo info) => info.Exists;
public byte[] ReadAllBytes(string path) => File.ReadAllBytes(path);
public void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors) =>
File.Replace(sourceFileName, destinationFileName, destinationBackupFileName, ignoreMetadataErrors);
public void Move(string sourceFileName, string destinationFileName) =>
File.Move(sourceFileName, destinationFileName);
public void WriteAndFlushAllBytes(string path, byte[] bytes)
{
using (var fileStream = new FileStream(path, FileMode.Create))
{
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Flush(flushToDisk: true);
}
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal partial class DefaultSymbolSearchUpdateEngine
{
private class PatchService : IPatchService
{
public byte[] ApplyPatch(byte[] databaseBytes, byte[] patchBytes)
{
return Patching.Delta.ApplyPatch(databaseBytes, patchBytes);
}
}
}
}
// 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 Microsoft.VisualStudio.RemoteControl;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal partial class DefaultSymbolSearchUpdateEngine
{
private class RemoteControlService : IRemoteControlService
{
public IRemoteControlClient CreateClient(string hostId, string serverPath, int pollingMinutes)
{
const string BaseUrl = "https://az700632.vo.msecnd.net/pub";
return new RemoteControlClient(hostId, BaseUrl, serverPath, pollingMinutes);
}
}
}
}
// 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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Elfie.Model;
using Microsoft.CodeAnalysis.Elfie.Model.Structures;
using Microsoft.CodeAnalysis.Elfie.Model.Tree;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Packaging;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
/// <summary>
/// A service which enables searching for packages matching certain criteria.
/// It works against an <see cref="Microsoft.CodeAnalysis.Elfie"/> database to find results.
///
/// This implementation also spawns a task which will attempt to keep that database up to
/// date by downloading patches on a daily basis.
/// </summary>
internal partial class DefaultSymbolSearchUpdateEngine : ISymbolSearchUpdateEngine
{
private ConcurrentDictionary<string, IAddReferenceDatabaseWrapper> _sourceToDatabase =
new ConcurrentDictionary<string, IAddReferenceDatabaseWrapper>();
public DefaultSymbolSearchUpdateEngine(HostWorkspaceServices workspaceServices)
: this(workspaceServices.GetService<IPackageInstallerService>(),
workspaceServices.GetService<ISymbolSearchLogService>(),
new RemoteControlService(),
new DelayService(),
new IOService(),
new PatchService(),
new DatabaseFactoryService(),
// Report all exceptions we encounter, but don't crash on them.
FatalError.ReportWithoutCrash,
new CancellationTokenSource())
{
}
/// <summary>
/// For testing purposes only.
/// </summary>
internal DefaultSymbolSearchUpdateEngine(
IPackageInstallerService installerService,
ISymbolSearchLogService logService,
IRemoteControlService remoteControlService,
IDelayService delayService,
IIOService ioService,
IPatchService patchService,
IDatabaseFactoryService databaseFactoryService,
Func<Exception, bool> reportAndSwallowException,
CancellationTokenSource cancellationTokenSource)
{
_installerService = installerService;
_delayService = delayService;
_ioService = ioService;
_logService = logService;
_remoteControlService = remoteControlService;
_patchService = patchService;
_databaseFactoryService = databaseFactoryService;
_reportAndSwallowException = reportAndSwallowException;
_cancellationTokenSource = cancellationTokenSource;
_cancellationToken = _cancellationTokenSource.Token;
}
//protected override void EnableService()
//{
// // When our service is enabled hook up to package source changes.
// // We need to know when the list of sources have changed so we can
// // kick off the work to process them.
// _installerService.PackageSourcesChanged += OnPackageSourcesChanged;
//}
//private void OnPackageSourcesChanged(object sender, EventArgs e)
//{
// StartWorking();
//}
//protected override void StartWorking()
//{
// // Kick off a database update. Wait a few seconds before starting so we don't
// // interfere too much with solution loading.
// var sources = _installerService.PackageSources;
// // Always pull down the nuget.org index. It contains the MS reference assembly index
// // inside of it.
// var allSources = sources.Concat(new PackageSource(NugetOrgSource, source: null));
// foreach (var source in allSources)
// {
// Task.Run(() => UpdateSourceInBackgroundAsync(source.Name));
// }
//}
//protected override void StopWorking()
//{
// _installerService.PackageSourcesChanged -= OnPackageSourcesChanged;
// _cancellationTokenSource.Cancel();
//}
public IEnumerable<PackageWithTypeResult> FindPackagesWithType(
string source, string name, int arity, CancellationToken cancellationToken)
{
IAddReferenceDatabaseWrapper databaseWrapper;
if (!_sourceToDatabase.TryGetValue(source, out databaseWrapper))
{
// Don't have a database to search.
yield break;
}
var database = databaseWrapper.Database;
if (name == "var")
{
// never find anything named 'var'.
yield break;
}
var query = new MemberQuery(name, isFullSuffix: true, isFullNamespace: false);
var symbols = new PartialArray<Symbol>(100);
if (query.TryFindMembers(database, ref symbols))
{
var types = FilterToViableTypes(symbols);
var typesFromPackagesUsedInOtherProjects = new List<Symbol>();
var typesFromPackagesNotUsedInOtherProjects = new List<Symbol>();
foreach (var type in types)
{
// Ignore any reference assembly results.
if (type.PackageName.ToString() != MicrosoftAssemblyReferencesName)
{
var packageName = type.PackageName.ToString();
if (_installerService.GetInstalledVersions(packageName).Any())
{
typesFromPackagesUsedInOtherProjects.Add(type);
}
else
{
typesFromPackagesNotUsedInOtherProjects.Add(type);
}
}
}
var result = new List<Symbol>();
// We always returm types from packages that we've use elsewhere in the project.
int? bestRank = null;
foreach (var type in typesFromPackagesUsedInOtherProjects)
{
yield return CreateResult(database, type);
}
// For all other hits include as long as the popularity is high enough.
// Popularity ranks are in powers of two. So if two packages differ by
// one rank, then one is at least twice as popular as the next. Two
// ranks would be four times as popular. Three ranks = 8 times, etc.
// etc. We keep packages that within 1 rank of the best package we find.
foreach (var type in typesFromPackagesNotUsedInOtherProjects)
{
var rank = GetRank(type);
bestRank = bestRank == null ? rank : Math.Max(bestRank.Value, rank);
if (Math.Abs(bestRank.Value - rank) > 1)
{
yield break;
}
yield return CreateResult(database, type);
}
}
}
public IEnumerable<ReferenceAssemblyWithTypeResult> FindReferenceAssembliesWithType(
string name, int arity, CancellationToken cancellationToken)
{
// Our reference assembly data is stored in the nuget.org DB.
IAddReferenceDatabaseWrapper databaseWrapper;
if (!_sourceToDatabase.TryGetValue(NugetOrgSource, out databaseWrapper))
{
// Don't have a database to search.
yield break;
}
var database = databaseWrapper.Database;
if (name == "var")
{
// never find anything named 'var'.
yield break;
}
var query = new MemberQuery(name, isFullSuffix: true, isFullNamespace: false);
var symbols = new PartialArray<Symbol>(100);
if (query.TryFindMembers(database, ref symbols))
{
var types = FilterToViableTypes(symbols);
foreach (var type in types)
{
// Only look at reference assembly results.
if (type.PackageName.ToString() == MicrosoftAssemblyReferencesName)
{
var nameParts = new List<string>();
GetFullName(nameParts, type.FullName.Parent);
yield return new ReferenceAssemblyWithTypeResult(
type.AssemblyName.ToString(), type.Name.ToString(), containingNamespaceNames: nameParts);
}
}
}
}
private List<Symbol> FilterToViableTypes(PartialArray<Symbol> symbols)
{
// Don't return nested types. Currently their value does not seem worth
// it given all the extra stuff we'd have to plumb through. Namely
// going down the "using static" code path and whatnot.
return new List<Symbol>(
from symbol in symbols
where this.IsType(symbol) && !this.IsType(symbol.Parent())
select symbol);
}
private PackageWithTypeResult CreateResult(AddReferenceDatabase database, Symbol type)
{
var nameParts = new List<string>();
GetFullName(nameParts, type.FullName.Parent);
var packageName = type.PackageName.ToString();
var version = database.GetPackageVersion(type.Index).ToString();
return new PackageWithTypeResult(
packageName: packageName,
typeName: type.Name.ToString(),
version: version,
containingNamespaceNames: nameParts);
}
private int GetRank(Symbol symbol)
{
Symbol rankingSymbol;
int rank;
if (!TryGetRankingSymbol(symbol, out rankingSymbol) ||
!int.TryParse(rankingSymbol.Name.ToString(), out rank))
{
return 0;
}
return rank;
}
private bool TryGetRankingSymbol(Symbol symbol, out Symbol rankingSymbol)
{
for (var current = symbol; current.IsValid; current = current.Parent())
{
if (current.Type == SymbolType.Package || current.Type == SymbolType.Version)
{
return TryGetRankingSymbolForPackage(current, out rankingSymbol);
}
}
rankingSymbol = default(Symbol);
return false;
}
private bool TryGetRankingSymbolForPackage(Symbol package, out Symbol rankingSymbol)
{
for (var child = package.FirstChild(); child.IsValid; child = child.NextSibling())
{
if (child.Type == SymbolType.PopularityRank)
{
rankingSymbol = child;
return true;
}
}
rankingSymbol = default(Symbol);
return false;
}
private bool IsType(Symbol symbol)
{
return symbol.Type.IsType();
}
private void GetFullName(List<string> nameParts, Path8 path)
{
if (!path.IsEmpty)
{
GetFullName(nameParts, path.Parent);
nameParts.Add(path.Name.ToString());
}
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Elfie.Model;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
// Wrapper types to ensure we delay load the elfie database.
internal interface IAddReferenceDatabaseWrapper
{
AddReferenceDatabase Database { get; }
}
internal class AddReferenceDatabaseWrapper : IAddReferenceDatabaseWrapper
{
public AddReferenceDatabase Database { get; }
public AddReferenceDatabaseWrapper(AddReferenceDatabase database)
{
Database = database;
}
}
}
// 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 Microsoft.CodeAnalysis.Elfie.Model;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal interface IDatabaseFactoryService
{
AddReferenceDatabase CreateDatabaseFromBytes(byte[] bytes);
}
}
// 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;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
/// <summary>
/// Used so we can mock out how the search service delays work for testing purposes.
/// </summary>
internal interface IDelayService
{
/// <summary>
/// The time to wait after a successful update (default = 1 day).
/// </summary>
TimeSpan UpdateSucceededDelay { get; }
/// <summary>
/// The time to wait after a simple expected sort of failure (i.e. IO exceptions,
/// network exceptions, etc). Things we can recover from and would expect would
/// be transient.
/// </summary>
TimeSpan ExpectedFailureDelay { get; }
/// <summary>
/// The time to wait after a catastrophic failed update (default = 1 day). For
/// example, if we download the full DB xml from the server and we cannot parse
/// it. Retrying soon after will not help. We'll just have to wait until proper
/// data is on the server for us to query.
/// </summary>
TimeSpan CatastrophicFailureDelay { get; }
/// <summary>
/// The time to wait after writing to disk fails (default = 10 seconds).
/// </summary>
TimeSpan FileWriteDelay { get; }
/// <summary>
/// How long to wait between each poll of the cache (default = 1 minute).
/// </summary>
TimeSpan CachePollDelay { get; }
}
}
// 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.IO;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
/// <summary>
/// Used so we can mock out how the search service does IO for testing purposes.
/// </summary>
internal interface IIOService
{
void Create(DirectoryInfo directory);
void Delete(FileInfo file);
bool Exists(FileSystemInfo info);
byte[] ReadAllBytes(string path);
void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors);
void Move(string sourceFileName, string destinationFileName);
void WriteAndFlushAllBytes(string path, byte[] bytes);
}
}
// 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.Composition;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
/// <summary>
/// Used so we can mock out logging in unit tests.
/// </summary>
internal interface ISymbolSearchLogService : IWorkspaceService
{
Task LogExceptionAsync(Exception e, string text);
Task LogInfoAsync(string text);
}
[ExportWorkspaceService(typeof(ISymbolSearchLogService)), Shared]
internal class DefaultSymbolSearchLogService : ISymbolSearchLogService
{
public Task LogExceptionAsync(Exception e, string text) => SpecializedTasks.EmptyTask;
public Task LogInfoAsync(string text) => SpecializedTasks.EmptyTask;
}
}
\ 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.
namespace Microsoft.CodeAnalysis.SymbolSearch
{
/// <summary>
/// Used so we can mock out patching in unit tests.
/// </summary>
internal interface IPatchService
{
byte[] ApplyPatch(byte[] databaseBytes, byte[] patchBytes);
}
}
// 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 Microsoft.VisualStudio.RemoteControl;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
/// <summary>
/// Used so we can mock out the remote control service in unit tests.
/// </summary>
internal interface IRemoteControlService
{
IRemoteControlClient CreateClient(string hostId, string serverPath, int pollingMinutes);
}
}
// 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.Composition;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal interface ISymbolSearchUpdateEngine : IWorkspaceService
{
}
[ExportWorkspaceServiceFactory(typeof(ISymbolSearchUpdateEngine)), Shared]
internal class DefaultSymbolSearchUpdateEngineFactory : IWorkspaceServiceFactory
{
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
return new DefaultSymbolSearchUpdateEngine(workspaceServices);
}
}
}
\ 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.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.CodeAnalysis.SymbolSearch.Patching
{
/// <summary>
/// Wrapper around the msdelta api so we can consume patches produced by the Elfie service.
/// Pinvokes and code provided by Dan Thompson
/// </summary>
internal static unsafe class Delta
{
[StructLayout(LayoutKind.Sequential)]
private struct DeltaInput
{
public byte* pBuf;
public IntPtr cbBuf; // SIZE_T, so different size on x86/x64
[MarshalAs(UnmanagedType.Bool)]
public bool editable;
public DeltaInput(byte* pBuf_, int cbBuf_, bool editable_) : this()
{
pBuf = pBuf_;
cbBuf = new IntPtr(cbBuf_);
editable = editable_;
}
public static DeltaInput Empty = new DeltaInput();
}
[StructLayout(LayoutKind.Sequential)]
private struct DeltaOutput
{
public IntPtr pBuf;
public IntPtr cbBuf; // SIZE_T, so different size on x86/x64
}
[Flags]
private enum DeltaApplyFlag : long
{
None = 0,
AllowPa19 = 0x00000001
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("msdelta.dll", SetLastError = true)]
private static extern bool ApplyDeltaB(
DeltaApplyFlag applyFlags,
DeltaInput source,
DeltaInput delta,
out DeltaOutput target);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("msdelta.dll", SetLastError = true)]
private static extern bool DeltaFree(IntPtr memory);
public static unsafe byte[] ApplyPatch(byte[] sourceBytes, byte[] patchBytes)
{
fixed (byte* pSourceBuf = sourceBytes)
fixed (byte* pPatchBuf = patchBytes)
{
DeltaInput ds = new DeltaInput(pSourceBuf, sourceBytes.Length, true);
DeltaInput dp = new DeltaInput(pPatchBuf, patchBytes.Length, true);
DeltaOutput output;
if (!ApplyDeltaB(DeltaApplyFlag.None,
ds,
dp,
out output))
{
throw new Win32Exception();
}
byte[] targetBytes = new byte[output.cbBuf.ToInt32()];
Marshal.Copy(output.pBuf, targetBytes, 0, targetBytes.Length);
DeltaFree(output.pBuf);
return targetBytes;
}
}
}
}
\ No newline at end of file
......@@ -51,13 +51,29 @@
<Compile Include="..\..\..\Compilers\Shared\GlobalAssemblyCacheHelpers\GlobalAssemblyCacheLocation.cs">
<Link>InternalUtilities\GlobalAssemblyCache.cs</Link>
</Compile>
<Compile Include="SymbolSearch\DefaultSymbolSearchUpdateEngine.DatabaseFactoryService.cs" />
<Compile Include="SymbolSearch\DefaultSymbolSearchUpdateEngine.DelayService.cs" />
<Compile Include="SymbolSearch\DefaultSymbolSearchUpdateEngine.IOService.cs" />
<Compile Include="SymbolSearch\DefaultSymbolSearchUpdateEngine.PatchService.cs" />
<Compile Include="SymbolSearch\DefaultSymbolSearchUpdateEngine.RemoteControlService.cs" />
<Compile Include="SymbolSearch\DefaultSymbolSearchUpdateEngine.cs" />
<Compile Include="Execution\DesktopReferenceSerializationServiceFactory.cs" />
<Compile Include="Execution\SerializationAnalyzerAssemblyLoader.cs" />
<Compile Include="SymbolSearch\ISymbolSearchUpdateEngine.cs" />
<Compile Include="Options\ExportOptionAttribute.cs" />
<Compile Include="InternalUtilities\FilePathUtilities.cs" />
<Compile Include="Log\EtwLogger.cs" />
<Compile Include="Log\RoslynEventSource.cs" />
<Compile Include="Options\Providers\ExportedOptionKeyOptionProvider.cs" />
<Compile Include="SymbolSearch\IAddReferenceDatabaseWrapper.cs" />
<Compile Include="SymbolSearch\IDatabaseFactoryService.cs" />
<Compile Include="SymbolSearch\IDelayService.cs" />
<Compile Include="SymbolSearch\IIOService.cs" />
<Compile Include="SymbolSearch\ILogService.cs" />
<Compile Include="SymbolSearch\IPatchService.cs" />
<Compile Include="SymbolSearch\IRemoteControlService.cs" />
<Compile Include="SymbolSearch\Patching\Delta.cs" />
<Compile Include="SymbolSearch\DefaultSymbolSearchUpdateEngine.Update.cs" />
<Compile Include="Utilities\Documentation\FileBasedXmlDocumentationProvider.cs" />
<Compile Include="Utilities\ReferencePathUtilities_Desktop.cs" />
<Compile Include="WorkspaceDesktopResources.Designer.cs">
......
{
"dependencies": {
"ManagedEsent": "1.9.4",
"Roslyn.Microsoft.Build": "0.0.2"
"Roslyn.Microsoft.Build": "0.0.2",
"Microsoft.CodeAnalysis.Elfie": {
"version": "0.10.6-rc2",
"suppressParent": "all"
},
"Microsoft.VisualStudio.RemoteControl": {
"version": "14.0.249-master2E2DC10C",
"suppressParent": "all"
},
},
"frameworks": {
"net46": { }
......
using Microsoft.CodeAnalysis.Options;
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.Shared.Options
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal class AddImportOptions
internal static class SymbolSearchOptions
{
public static readonly Option<bool> Enabled = new Option<bool>(nameof(SymbolSearchOptions), nameof(Enabled), defaultValue: true);
public static PerLanguageOption<bool> SuggestForTypesInReferenceAssemblies =
new PerLanguageOption<bool>(nameof(AddImportOptions), nameof(SuggestForTypesInReferenceAssemblies), defaultValue: false,
new PerLanguageOption<bool>(nameof(SymbolSearchOptions), nameof(SuggestForTypesInReferenceAssemblies), defaultValue: false,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.SuggestForTypesInReferenceAssemblies"));
public static PerLanguageOption<bool> SuggestForTypesInNuGetPackages =
new PerLanguageOption<bool>(nameof(AddImportOptions), nameof(SuggestForTypesInNuGetPackages), defaultValue: false,
new PerLanguageOption<bool>(nameof(SymbolSearchOptions), nameof(SuggestForTypesInNuGetPackages), defaultValue: false,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.SuggestForTypesInNuGetPackages"));
}
}
using Microsoft.CodeAnalysis.Options;
// 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 Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
namespace Microsoft.CodeAnalysis.Shared.Options
namespace Microsoft.CodeAnalysis.SymbolSearch
{
[ExportOptionProvider, Shared]
internal class AddImportOptionsProvider : IOptionProvider
internal class SymbolSearchOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = ImmutableArray.Create<IOption>(
AddImportOptions.SuggestForTypesInReferenceAssemblies,
AddImportOptions.SuggestForTypesInNuGetPackages);
SymbolSearchOptions.Enabled,
SymbolSearchOptions.SuggestForTypesInReferenceAssemblies,
SymbolSearchOptions.SuggestForTypesInNuGetPackages);
public IEnumerable<IOption> GetOptions() => _options;
}
......
......@@ -394,6 +394,7 @@
<Compile Include="Options\IWorkspaceOptionService.cs" />
<Compile Include="Shared\RuntimeOptions.cs" />
<Compile Include="Shared\RuntimeOptionsProvider.cs" />
<Compile Include="Shared\Utilities\IOUtilities.cs" />
<Compile Include="Shared\Utilities\IStreamingProgressTracker.cs" />
<Compile Include="Shared\Utilities\StreamingProgressTracker.cs" />
<Compile Include="Options\OptionStorageLocation.cs" />
......@@ -493,12 +494,14 @@
<Compile Include="SymbolKey\SymbolKey.ArrayTypeSymbolKey.cs" />
<Compile Include="SymbolKey\SymbolKey.SymbolKeyWriter.cs" />
<Compile Include="SymbolKey\SymbolKey.cs" />
<Compile Include="SymbolSearch\SymbolSearchOptionsProvider.cs" />
<Compile Include="SymbolSearch\ISymbolSearchService.cs" />
<Compile Include="FindSymbols\SymbolTree\ISymbolTreeInfoCacheService.cs" />
<Compile Include="FindSymbols\FindReferences\MetadataUnifyingEquivalenceComparer.cs" />
<Compile Include="Shared\Utilities\IProgressTracker.cs" />
<Compile Include="SolutionCrawler\NullSolutionCrawlerRegisterationService.cs" />
<Compile Include="SolutionCrawler\WellKnownSolutionCrawlerAnalyzers.cs" />
<Compile Include="SymbolSearch\SymbolSearchOptions.cs" />
<Compile Include="Utilities\ArraySlice.cs" />
<Compile Include="Utilities\BKTree.cs" />
<Compile Include="FindSymbols\SyntaxTree\AbstractSyntaxTreeInfo.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册