提交 5d6078cd 编写于 作者: O Omar Tawfik

Update latest from master

......@@ -65,6 +65,10 @@
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XmlDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
......
......@@ -65,6 +65,10 @@
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XmlDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
......
......@@ -2729,5 +2729,57 @@ public void Deconstruct(out dynamic x, out dynamic y)
Diagnostic(ErrorCode.WRN_UnreferencedVar, "y4").WithArguments("y4").WithLocation(9, 25)
);
}
[Fact]
public void DeclarationInsideNameof()
{
string source = @"
class Program
{
static void Main()
{
string s = nameof((int x1, var x2) = (1, 2)).ToString();
string s1 = x1, s2 = x2;
}
}
";
var comp = CreateCompilationWithMscorlib(source, references: s_valueTupleRefs);
comp.VerifyDiagnostics(
// (6,28): error CS8185: A declaration is not allowed in this context.
// string s = nameof((int x1, var x2) = (1, 2)).ToString();
Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "int x1").WithLocation(6, 28),
// (6,27): error CS8081: Expression does not have a name.
// string s = nameof((int x1, var x2) = (1, 2)).ToString();
Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "(int x1, var x2) = (1, 2)").WithLocation(6, 27),
// (7,21): error CS0029: Cannot implicitly convert type 'int' to 'string'
// string s1 = x1, s2 = x2;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "x1").WithArguments("int", "string").WithLocation(7, 21),
// (7,30): error CS0029: Cannot implicitly convert type 'int' to 'string'
// string s1 = x1, s2 = x2;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "x2").WithArguments("int", "string").WithLocation(7, 30),
// (7,21): error CS0165: Use of unassigned local variable 'x1'
// string s1 = x1, s2 = x2;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(7, 21),
// (7,30): error CS0165: Use of unassigned local variable 'x2'
// string s1 = x1, s2 = x2;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x2").WithArguments("x2").WithLocation(7, 30)
);
var tree = comp.SyntaxTrees.First();
var model = comp.GetSemanticModel(tree);
var designations = tree.GetCompilationUnitRoot().DescendantNodes().OfType<SingleVariableDesignationSyntax>().ToArray();
Assert.Equal(2, designations.Count());
var refs = tree.GetCompilationUnitRoot().DescendantNodes().OfType<IdentifierNameSyntax>();
var x1 = model.GetDeclaredSymbol(designations[0]);
Assert.Equal("x1", x1.Name);
Assert.Equal("System.Int32", ((LocalSymbol)x1).Type.ToTestDisplayString());
Assert.Same(x1, model.GetSymbolInfo(refs.Where(r => r.Identifier.ValueText == "x1").Single()).Symbol);
var x2 = model.GetDeclaredSymbol(designations[1]);
Assert.Equal("x2", x2.Name);
Assert.Equal("System.Int32", ((LocalSymbol)x2).Type.ToTestDisplayString());
Assert.Same(x2, model.GetSymbolInfo(refs.Where(r => r.Identifier.ValueText == "x2").Single()).Symbol);
}
}
}
......@@ -11765,5 +11765,43 @@ static bool Dummy(params object[] data)
var z2Ref = GetReferences(tree, "z2").Single();
Assert.Equal("System.Boolean", compilation.GetSemanticModel(tree).GetTypeInfo(z2Ref).Type.ToTestDisplayString());
}
[Fact]
public void DeclarationInsideNameof()
{
string source = @"
class Program
{
static void Main(int i)
{
string s = nameof(M(i is var x1, x1)).ToString();
string s1 = x1;
}
static void M(bool b, int i) {}
}
";
var comp = CreateCompilationWithMscorlib(source);
comp.VerifyDiagnostics(
// (6,27): error CS8081: Expression does not have a name.
// string s = nameof(M(i is var x1, x1)).ToString();
Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "M(i is var x1, x1)").WithLocation(6, 27),
// (7,21): error CS0029: Cannot implicitly convert type 'int' to 'string'
// string s1 = x1;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "x1").WithArguments("int", "string").WithLocation(7, 21),
// (7,21): error CS0165: Use of unassigned local variable 'x1'
// string s1 = x1;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(7, 21)
);
var tree = comp.SyntaxTrees.First();
var model = comp.GetSemanticModel(tree);
var designation = GetPatternDeclarations(tree).Single();
var refs = GetReferences(tree, "x1").ToArray();
VerifyModelForDeclarationPattern(model, designation, refs);
var x1 = (LocalSymbol)model.GetDeclaredSymbol(designation);
Assert.Equal("System.Int32", x1.Type.ToTestDisplayString());
}
}
}
......@@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.DocumentationComments;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
......@@ -75,7 +76,7 @@ internal abstract partial class AbstractSemanticQuickInfoProvider : AbstractQuic
foreach (var link in linkedDocumentIds)
{
var linkedDocument = document.Project.Solution.GetDocument(link);
var linkedToken = await FindTokenInLinkedDocument(token, linkedDocument, cancellationToken).ConfigureAwait(false);
var linkedToken = await FindTokenInLinkedDocument(token, document, linkedDocument, cancellationToken).ConfigureAwait(false);
if (linkedToken != default(SyntaxToken))
{
......@@ -116,7 +117,7 @@ internal abstract partial class AbstractSemanticQuickInfoProvider : AbstractQuic
return await CreateContentAsync(document.Project.Solution.Workspace, token, bestBinding.Item2, bestBinding.Item3, supportedPlatforms, cancellationToken).ConfigureAwait(false);
}
private async Task<SyntaxToken> FindTokenInLinkedDocument(SyntaxToken token, Document linkedDocument, CancellationToken cancellationToken)
private async Task<SyntaxToken> FindTokenInLinkedDocument(SyntaxToken token, Document originalDocument, Document linkedDocument, CancellationToken cancellationToken)
{
if (!linkedDocument.SupportsSyntaxTree)
{
......@@ -125,13 +126,24 @@ private async Task<SyntaxToken> FindTokenInLinkedDocument(SyntaxToken token, Doc
var root = await linkedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
// Don't search trivia because we want to ignore inactive regions
var linkedToken = root.FindToken(token.SpanStart);
try
{
// Don't search trivia because we want to ignore inactive regions
var linkedToken = root.FindToken(token.SpanStart);
// The new and old tokens should have the same span?
if (token.Span == linkedToken.Span)
// The new and old tokens should have the same span?
if (token.Span == linkedToken.Span)
{
return linkedToken;
}
}
catch (Exception e)
{
return linkedToken;
// We are seeing linked files with different spans cause FindToken to crash.
// Capturing more information for https://devdiv.visualstudio.com/DevDiv/_workitems?id=209299
var originalText = await originalDocument.GetTextAsync().ConfigureAwait(false);
var linkedText = await linkedDocument.GetTextAsync().ConfigureAwait(false);
FatalError.Report(e);
}
return default(SyntaxToken);
......
......@@ -16,7 +16,7 @@
namespace Roslyn.Test.Utilities.Remote
{
internal class InProcRemoteHostClient : RemoteHostClient
internal sealed class InProcRemoteHostClient : RemoteHostClient
{
private readonly InProcRemoteServices _inprocServices;
private readonly JsonRpc _rpc;
......@@ -47,10 +47,12 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool
{
_inprocServices = inprocServices;
_rpc = JsonRpc.Attach(stream, target: this);
_rpc = new JsonRpc(stream, stream, target: this);
// handle disconnected situation
_rpc.Disconnected += OnRpcDisconnected;
_rpc.StartListening();
}
public AssetStorage AssetStorage => _inprocServices.AssetStorage;
......
......@@ -39,7 +39,7 @@
<package id="System.Collections.Immutable" version="1.1.36" skipAssemblyReferences="false" />
<package id="System.Reflection.Metadata" version="1.0.21" skipAssemblyReferences="false" />
<package id="Microsoft.Composition" version="1.0.27" skipAssemblyReferences="false" />
<package id="NuGet.CommandLine" />
<package id="NuGet.CommandLine" version="2.8.5" />
</packages>
</WizardData>
</VSTemplate>
......@@ -41,7 +41,7 @@
<package id="System.Collections.Immutable" version="1.1.36" skipAssemblyReferences="false" />
<package id="System.Reflection.Metadata" version="1.0.21" skipAssemblyReferences="false" />
<package id="Microsoft.Composition" version="1.0.27" skipAssemblyReferences="false" />
<package id="NuGet.CommandLine" />
<package id="NuGet.CommandLine" version="2.8.5" />
</packages>
</WizardData>
</VSTemplate>
\ No newline at end of file
......@@ -25,7 +25,8 @@ internal class JsonRpcClient : IDisposable
var target = useThisAsCallback ? this : callbackTarget;
_cancellationToken = cancellationToken;
_rpc = JsonRpc.Attach(stream, target);
_rpc = new JsonRpc(stream, stream, target);
_rpc.Disconnected += OnDisconnected;
}
......@@ -84,6 +85,13 @@ public void Dispose()
_rpc.Dispose();
}
protected void StartListening()
{
// due to this issue - https://github.com/dotnet/roslyn/issues/16900#issuecomment-277378950
// _rpc need to be explicitly started
_rpc.StartListening();
}
protected virtual void OnDisposed()
{
// do nothing
......
......@@ -114,6 +114,8 @@ public ServiceJsonRpcClient(Stream stream, object callbackTarget, CancellationTo
{
// this one doesn't need cancellation token since it has nothing to cancel
_callbackTarget = callbackTarget;
StartListening();
}
}
......@@ -137,6 +139,8 @@ public SnapshotJsonRpcClient(JsonRpcSession owner, Stream stream, CancellationTo
{
_owner = owner;
_source = new CancellationTokenSource();
StartListening();
}
private PinnedRemotableDataScope PinnedScope => _owner.PinnedScope;
......
......@@ -18,7 +18,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Remote
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Workspace = Microsoft.CodeAnalysis.Workspace;
internal partial class ServiceHubRemoteHostClient : RemoteHostClient
internal sealed partial class ServiceHubRemoteHostClient : RemoteHostClient
{
private readonly HubClient _hubClient;
private readonly JsonRpc _rpc;
......@@ -81,10 +81,12 @@ private static async Task RegisterWorkspaceHostAsync(Workspace workspace, Remote
_hubClient = hubClient;
_hostGroup = hostGroup;
_rpc = JsonRpc.Attach(stream, target: this);
_rpc = new JsonRpc(stream, stream, target: this);
// handle disconnected situation
_rpc.Disconnected += OnRpcDisconnected;
_rpc.StartListening();
}
protected override async Task<Session> CreateServiceSessionAsync(string serviceName, PinnedRemotableDataScope snapshot, object callbackTarget, CancellationToken cancellationToken)
......
......@@ -8,6 +8,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
......@@ -177,64 +178,76 @@ private static bool IsRenameValid(ConflictResolution conflictResolution, ISymbol
IDictionary<Location, Location> reverseMappedLocations,
CancellationToken cancellationToken)
{
if (renamedSymbol.ContainingSymbol.IsKind(SymbolKind.NamedType))
try
{
var otherThingsNamedTheSame = renamedSymbol.ContainingType.GetMembers(renamedSymbol.Name)
.Where(s => !s.Equals(renamedSymbol) &&
string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal) &&
(s.Kind != SymbolKind.Method || renamedSymbol.Kind != SymbolKind.Method));
AddConflictingSymbolLocations(otherThingsNamedTheSame, conflictResolution, reverseMappedLocations);
}
if (renamedSymbol.IsKind(SymbolKind.Namespace) && renamedSymbol.ContainingSymbol.IsKind(SymbolKind.Namespace))
{
var otherThingsNamedTheSame = ((INamespaceSymbol)renamedSymbol.ContainingSymbol).GetMembers(renamedSymbol.Name)
.Where(s => !s.Equals(renamedSymbol) &&
!s.IsKind(SymbolKind.Namespace) &&
string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal));
if (renamedSymbol.ContainingSymbol.IsKind(SymbolKind.NamedType))
{
var otherThingsNamedTheSame = renamedSymbol.ContainingType.GetMembers(renamedSymbol.Name)
.Where(s => !s.Equals(renamedSymbol) &&
string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal) &&
(s.Kind != SymbolKind.Method || renamedSymbol.Kind != SymbolKind.Method));
AddConflictingSymbolLocations(otherThingsNamedTheSame, conflictResolution, reverseMappedLocations);
}
AddConflictingSymbolLocations(otherThingsNamedTheSame, conflictResolution, reverseMappedLocations);
}
if (renamedSymbol.IsKind(SymbolKind.NamedType) && renamedSymbol.ContainingSymbol is INamespaceOrTypeSymbol)
{
var otherThingsNamedTheSame = ((INamespaceOrTypeSymbol)renamedSymbol.ContainingSymbol).GetMembers(renamedSymbol.Name)
.Where(s => !s.Equals(renamedSymbol) &&
string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal));
var conflictingSymbolLocations = otherThingsNamedTheSame.Where(s => !s.IsKind(SymbolKind.Namespace));
if (otherThingsNamedTheSame.Any(s => s.IsKind(SymbolKind.Namespace)))
if (renamedSymbol.IsKind(SymbolKind.Namespace) && renamedSymbol.ContainingSymbol.IsKind(SymbolKind.Namespace))
{
conflictingSymbolLocations = conflictingSymbolLocations.Concat(renamedSymbol);
var otherThingsNamedTheSame = ((INamespaceSymbol)renamedSymbol.ContainingSymbol).GetMembers(renamedSymbol.Name)
.Where(s => !s.Equals(renamedSymbol) &&
!s.IsKind(SymbolKind.Namespace) &&
string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal));
AddConflictingSymbolLocations(otherThingsNamedTheSame, conflictResolution, reverseMappedLocations);
}
AddConflictingSymbolLocations(conflictingSymbolLocations, conflictResolution, reverseMappedLocations);
}
if (renamedSymbol.IsKind(SymbolKind.NamedType) && renamedSymbol.ContainingSymbol is INamespaceOrTypeSymbol)
{
var otherThingsNamedTheSame = ((INamespaceOrTypeSymbol)renamedSymbol.ContainingSymbol).GetMembers(renamedSymbol.Name)
.Where(s => !s.Equals(renamedSymbol) &&
string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal));
// Some types of symbols (namespaces, cref stuff, etc) might not have ContainingAssemblies
if (renamedSymbol.ContainingAssembly != null)
{
var project = conflictResolution.NewSolution.GetProject(renamedSymbol.ContainingAssembly, cancellationToken);
var conflictingSymbolLocations = otherThingsNamedTheSame.Where(s => !s.IsKind(SymbolKind.Namespace));
if (otherThingsNamedTheSame.Any(s => s.IsKind(SymbolKind.Namespace)))
{
conflictingSymbolLocations = conflictingSymbolLocations.Concat(renamedSymbol);
}
// There also might be language specific rules we need to include
var languageRenameService = project.LanguageServices.GetService<IRenameRewriterLanguageService>();
var languageConflicts = await languageRenameService.ComputeDeclarationConflictsAsync(
conflictResolution.ReplacementText,
renamedSymbol,
renameSymbol,
referencedSymbols,
conflictResolution.OldSolution,
conflictResolution.NewSolution,
reverseMappedLocations,
cancellationToken).ConfigureAwait(false);
AddConflictingSymbolLocations(conflictingSymbolLocations, conflictResolution, reverseMappedLocations);
}
foreach (var languageConflict in languageConflicts)
// Some types of symbols (namespaces, cref stuff, etc) might not have ContainingAssemblies
if (renamedSymbol.ContainingAssembly != null)
{
conflictResolution.AddOrReplaceRelatedLocation(new RelatedLocation(languageConflict.SourceSpan, conflictResolution.OldSolution.GetDocument(languageConflict.SourceTree).Id, RelatedLocationType.UnresolvableConflict));
var project = conflictResolution.NewSolution.GetProject(renamedSymbol.ContainingAssembly, cancellationToken);
// There also might be language specific rules we need to include
var languageRenameService = project.LanguageServices.GetService<IRenameRewriterLanguageService>();
var languageConflicts = await languageRenameService.ComputeDeclarationConflictsAsync(
conflictResolution.ReplacementText,
renamedSymbol,
renameSymbol,
referencedSymbols,
conflictResolution.OldSolution,
conflictResolution.NewSolution,
reverseMappedLocations,
cancellationToken).ConfigureAwait(false);
foreach (var languageConflict in languageConflicts)
{
conflictResolution.AddOrReplaceRelatedLocation(new RelatedLocation(languageConflict.SourceSpan, conflictResolution.OldSolution.GetDocument(languageConflict.SourceTree).Id, RelatedLocationType.UnresolvableConflict));
}
}
}
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
{
// A NullReferenceException is happening in this method, but the dumps do not
// contain information about this stack frame because this method is async and
// therefore the exception filter in IdentifyConflictsAsync is insufficient.
// See https://devdiv.visualstudio.com/DevDiv/_workitems?_a=edit&id=378642
throw ExceptionUtilities.Unreachable;
}
}
internal static void AddConflictingParametersOfProperties(
......
......@@ -49,6 +49,27 @@ public abstract partial class Workspace : IDisposable
private Action<string> _testMessageLogger;
/// <summary>
/// <see cref="OnProjectRemoved"/> takes the <see cref="_serializationLock"/>, but can also
/// cause Shared Project IVsHierarchys to notify us that their context hierarchy has
/// changed while we are still holding the lock. In response to this, we try to set the new
/// active context document for open files, which also tries to take the lock, and we
/// deadlock.
///
/// For.NET Framework Projects that reference Shared Projects, two things prevent deadlocks
/// when projects unload. During solution close, any Shared Projects are disconnected
/// before the projects start to unload, so no IVsHierarchy events are fired. During a
/// single project unload, we receive notification of the context hierarchy change before
/// the project is unloaded, avoiding any IVsHierarchy events if we tell the shared
/// hierarchy to set its context hierarchy to what it already is.
///
/// Neither of these behaviors are safe to rely on with .NET Standard (CPS) projects, so we
/// have to prevent the deadlock ourselves. We do this by remembering if we're already in
/// the serialization lock due to project unload, and then not take the lock to update
/// document contexts if so (but continuing to lock if it's not during a project unload).
/// </summary>
private ThreadLocal<bool> _isProjectUnloading = new ThreadLocal<bool>(() => false);
/// <summary>
/// Constructs a new workspace instance.
/// </summary>
......@@ -415,15 +436,24 @@ protected internal virtual void OnProjectRemoved(ProjectId projectId)
{
using (_serializationLock.DisposableWait())
{
CheckProjectIsInCurrentSolution(projectId);
this.CheckProjectCanBeRemoved(projectId);
_isProjectUnloading.Value = true;
var oldSolution = this.CurrentSolution;
try
{
CheckProjectIsInCurrentSolution(projectId);
this.CheckProjectCanBeRemoved(projectId);
var oldSolution = this.CurrentSolution;
this.ClearProjectData(projectId);
var newSolution = this.SetCurrentSolution(oldSolution.RemoveProject(projectId));
this.ClearProjectData(projectId);
var newSolution = this.SetCurrentSolution(oldSolution.RemoveProject(projectId));
this.RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind.ProjectRemoved, oldSolution, newSolution, projectId);
this.RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind.ProjectRemoved, oldSolution, newSolution, projectId);
}
finally
{
_isProjectUnloading.Value = false;
}
}
}
......
......@@ -335,7 +335,14 @@ protected void OnDocumentContextUpdated(DocumentId documentId)
if (container != null)
{
OnDocumentContextUpdated(documentId, container);
if (_isProjectUnloading.Value)
{
OnDocumentContextUpdated_NoSerializationLock(documentId, container);
}
else
{
OnDocumentContextUpdated(documentId, container);
}
}
}
......@@ -346,17 +353,22 @@ internal void OnDocumentContextUpdated(DocumentId documentId, SourceTextContaine
{
using (_serializationLock.DisposableWait())
{
DocumentId oldActiveContextDocumentId;
OnDocumentContextUpdated_NoSerializationLock(documentId, container);
}
}
using (_stateLock.DisposableWait())
{
oldActiveContextDocumentId = _bufferToDocumentInCurrentContextMap[container];
_bufferToDocumentInCurrentContextMap[container] = documentId;
}
internal void OnDocumentContextUpdated_NoSerializationLock(DocumentId documentId, SourceTextContainer container)
{
DocumentId oldActiveContextDocumentId;
// fire and forget
this.RaiseDocumentActiveContextChangedEventAsync(container, oldActiveContextDocumentId: oldActiveContextDocumentId, newActiveContextDocumentId: documentId);
using (_stateLock.DisposableWait())
{
oldActiveContextDocumentId = _bufferToDocumentInCurrentContextMap[container];
_bufferToDocumentInCurrentContextMap[container] = documentId;
}
// fire and forget
this.RaiseDocumentActiveContextChangedEventAsync(container, oldActiveContextDocumentId: oldActiveContextDocumentId, newActiveContextDocumentId: documentId);
}
protected void CheckDocumentIsClosed(DocumentId documentId)
......
......@@ -9,8 +9,9 @@ namespace Microsoft.CodeAnalysis.Remote
internal partial class CodeAnalysisService : ServiceHubServiceBase
{
public CodeAnalysisService(Stream stream, IServiceProvider serviceProvider) :
base(stream, serviceProvider)
base(serviceProvider, stream)
{
Rpc.StartListening();
}
}
}
......@@ -39,9 +39,10 @@ static RemoteHostService()
}
public RemoteHostService(Stream stream, IServiceProvider serviceProvider) :
base(stream, serviceProvider)
base(serviceProvider, stream)
{
// this service provide a way for client to make sure remote host is alive
Rpc.StartListening();
}
public string Connect(string host)
......
......@@ -13,10 +13,12 @@ internal partial class RemoteSymbolSearchUpdateEngine : ServiceHubServiceBase, I
private readonly SymbolSearchUpdateEngine _updateEngine;
public RemoteSymbolSearchUpdateEngine(Stream stream, IServiceProvider serviceProvider)
: base(stream, serviceProvider)
: base(serviceProvider, stream)
{
_updateEngine = new SymbolSearchUpdateEngine(
new LogService(this), updateCancellationToken: this.CancellationToken);
Rpc.StartListening();
}
public Task UpdateContinuouslyAsync(string sourceName, string localSettingsDirectory)
......
......@@ -20,9 +20,11 @@ internal partial class SnapshotService : ServiceHubServiceBase
private AssetSource _source;
public SnapshotService(Stream stream, IServiceProvider serviceProvider) :
base(stream, serviceProvider)
base(serviceProvider, stream)
{
_gate = new object();
Rpc.StartListening();
}
public override void Initialize(int sessionId, byte[] solutionChecksum)
......
......@@ -29,6 +29,7 @@ internal abstract class ServiceHubServiceBase : IDisposable
private Checksum _solutionChecksumOpt;
private RoslynServices _lazyRoslynServices;
[Obsolete("For backward compatibility. this will be removed once all callers moved to new ctor")]
protected ServiceHubServiceBase(Stream stream, IServiceProvider serviceProvider)
{
_instanceId = Interlocked.Add(ref s_instanceId, 1);
......@@ -46,6 +47,26 @@ protected ServiceHubServiceBase(Stream stream, IServiceProvider serviceProvider)
Rpc.Disconnected += OnRpcDisconnected;
}
protected ServiceHubServiceBase(IServiceProvider serviceProvider, Stream stream)
{
_instanceId = Interlocked.Add(ref s_instanceId, 1);
// in unit test, service provider will return asset storage, otherwise, use the default one
AssetStorage = (AssetStorage)serviceProvider.GetService(typeof(AssetStorage)) ?? AssetStorage.Default;
Logger = (TraceSource)serviceProvider.GetService(typeof(TraceSource));
Logger.TraceInformation($"{DebugInstanceString} Service instance created");
_cancellationTokenSource = new CancellationTokenSource();
CancellationToken = _cancellationTokenSource.Token;
// due to this issue - https://github.com/dotnet/roslyn/issues/16900#issuecomment-277378950
// all sub type must explicitly start JsonRpc once everything is
// setup
Rpc = new JsonRpc(stream, stream, this);
Rpc.Disconnected += OnRpcDisconnected;
}
protected string DebugInstanceString => $"{GetType()} ({_instanceId})";
protected RoslynServices RoslynServices
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册