Skip to content

Commit

Permalink
Merge pull request #31076 from dotnet/merges/dev16.0.x-to-dev16.0-pre…
Browse files Browse the repository at this point in the history
…view2

Merge dev16.0.x to dev16.0-preview2
  • Loading branch information
dotnet-automerge-bot committed Nov 12, 2018
2 parents e67cb50 + 7abb79c commit ce16eef
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,29 @@ IEnumerable<PortableExecutableReference> GetProject3MetadataReferences()
}
}


[WpfFact]
[Trait(Traits.Feature, Traits.Features.ProjectSystemShims)]
public void RemoveProjectConvertsProjectReferencesBack()
{
using (var environment = new TestEnvironment())
{
var project1 = CreateCSharpCPSProject(environment, "project1", commandLineArguments: @"/out:c:\project1.dll");
var project2 = CreateCSharpCPSProject(environment, "project2");

// Add project reference as metadata reference: since this is known to be the output path of project1, the metadata reference is converted to a project reference
project2.AddMetadataReference(@"c:\project1.dll", new MetadataReferenceProperties());
Assert.Single(environment.Workspace.CurrentSolution.GetProject(project2.Id).AllProjectReferences);

// Remove project1. project2's reference should have been converted back
project1.Dispose();
Assert.Empty(environment.Workspace.CurrentSolution.GetProject(project2.Id).AllProjectReferences);
Assert.Single(environment.Workspace.CurrentSolution.GetProject(project2.Id).MetadataReferences);

project2.Dispose();
}
}

[WpfFact]
[Trait(Traits.Feature, Traits.Features.ProjectSystemShims)]
public void AddRemoveAnalyzerReference_CPS()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ protected virtual IVsContainedLanguage CreateContainedLanguage(
IVsHierarchy hierarchy, uint itemid)
{
return new ContainedLanguage<TPackage, TLanguageService>(
bufferCoordinator, this.Package.ComponentModel, project, hierarchy, itemid,
bufferCoordinator, this.Package.ComponentModel, project, hierarchy, itemid, projectTrackerOpt: null, project.Id,
(TLanguageService)this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public AbstractProject(
Hierarchy = hierarchy;
Guid = projectGuid;
Language = language;
ProjectTracker = projectTracker;
_visualStudioWorkspace = workspace;

this.DisplayName = hierarchy != null && hierarchy.TryGetName(out var name) ? name : projectSystemName;
Expand Down Expand Up @@ -112,9 +113,12 @@ protected virtual string GetOutputFilePath()

internal HostDiagnosticUpdateSource HostDiagnosticUpdateSource { get; }

public virtual ProjectId Id => VisualStudioProject.Id;
public virtual ProjectId Id => VisualStudioProject?.Id ?? ExplicitId;

internal ProjectId ExplicitId { get; set; }

public string Language { get; }
public VisualStudioProjectTracker ProjectTracker { get; }

/// <summary>
/// The <see cref="IVsHierarchy"/> for this project. NOTE: May be null in Deferred Project Load cases.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@

namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
{
[Obsolete("This is a compatibility shim for TypeScript; please do not use it.")]
[Obsolete("This is a compatibility shim for TypeScript and Live Share; please do not use it.")]
internal sealed class DocumentProvider
{
[Obsolete("This is a compatibility shim for Live Share; please do not use it.")]
public DocumentProvider(VisualStudioProjectTracker projectTracker, IServiceProvider serviceProvider, VisualStudioDocumentTrackingService documentTrackingService)
{
}

[Obsolete("This overload is a compatibility shim for TypeScript; please do not use it.")]
public IVisualStudioHostDocument TryGetDocumentForFile(
AbstractProject hostProject,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Extensions;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
{
Expand All @@ -16,22 +18,53 @@ internal sealed partial class VisualStudioProjectTracker
private readonly VisualStudioProjectFactory _projectFactory;
internal IThreadingContext ThreadingContext { get; }

internal ImmutableArray<AbstractProject> ImmutableProjects => ImmutableArray<AbstractProject>.Empty;
[Obsolete("This is a compatibility shim for Live Share; please do not use it.")]
internal ImmutableArray<AbstractProject> ImmutableProjects => _projects.Values.ToImmutableArray();

internal HostWorkspaceServices WorkspaceServices => _workspace.Services;

[Obsolete("This is a compatibility shim for TypeScript; please do not use it.")]
private readonly Dictionary<ProjectId, AbstractProject> _typeScriptProjects = new Dictionary<ProjectId, AbstractProject>();
[Obsolete("This is a compatibility shim for TypeScript and Live Share; please do not use it.")]
private readonly Dictionary<ProjectId, AbstractProject> _projects = new Dictionary<ProjectId, AbstractProject>();

[Obsolete("This is a compatibility shim; please do not use it.")]
public VisualStudioProjectTracker(Workspace workspace, VisualStudioProjectFactory projectFactory, IThreadingContext threadingContext)
{
_workspace = workspace;
_projectFactory = projectFactory;
ThreadingContext = threadingContext;
DocumentProvider = new DocumentProvider(this, null, null);
}

[Obsolete("This is a compatibility shim for Live Share; please do not use it.")]
public VisualStudioProjectTracker(IServiceProvider serviceProvider, Workspace workspace)
{
_workspace = workspace;
ThreadingContext = serviceProvider.GetMefService<IThreadingContext>();

// This is used by Live Share to target their own workspace which is not the standard VS workspace; as a result this shouldn't have a project factory
// at all, because that's only targeting the VisualStudioWorkspace.
_projectFactory = null;

// We don't set DocumentProvider, because Live Share creates their own and then sets it later.
}

[Obsolete("This is a compatibility shim for TypeScript; please do not use it.")]
public DocumentProvider DocumentProvider => new DocumentProvider();
public DocumentProvider DocumentProvider { get; set; }

public Workspace Workspace => _workspace;

[Obsolete("This is a compatibility shim for Live Share; please do not use it.")]
public void InitializeProviders(DocumentProvider documentProvider, VisualStudioMetadataReferenceManager metadataReferenceProvider, VisualStudioRuleSetManager ruleSetFileProvider)
{
DocumentProvider = documentProvider;
}

[Obsolete("This is a compatibility shim for Live Share; please do not use it.")]
public void StartPushingToWorkspaceAndNotifyOfOpenDocuments(IEnumerable<AbstractProject> projects)
{
// This shim doesn't expect to get actual things passed to it
Debug.Assert(!projects.Any());
}

/*
Expand Down Expand Up @@ -62,7 +95,7 @@ public ProjectId GetOrCreateProjectIdForPath(string filePath, string projectDisp
public AbstractProject GetProject(ProjectId projectId)
{
// HACK: if we have a TypeScript project, they expect to return the real thing deriving from AbstractProject
if (_typeScriptProjects.TryGetValue(projectId, out var typeScriptProject))
if (_projects.TryGetValue(projectId, out var typeScriptProject))
{
return typeScriptProject;
}
Expand Down Expand Up @@ -110,36 +143,52 @@ public StubProject(VisualStudioProjectTracker projectTracker, Project project)
public override ProjectId Id => _id;
}

[Obsolete("This is a compatibility shim for TypeScript; please do not use it.")]
[Obsolete("This is a compatibility shim for TypeScript and Live Share; please do not use it.")]
public void AddProject(AbstractProject project)
{
var creationInfo = new VisualStudioProjectCreationInfo
if (_projectFactory != null)
{
var creationInfo = new VisualStudioProjectCreationInfo
{
AssemblyName = project.AssemblyName,
FilePath = project.ProjectFilePath,
Hierarchy = project.Hierarchy,
ProjectGuid = project.Guid,
};
project.VisualStudioProject = _projectFactory.CreateAndAddToWorkspace(project.ProjectSystemName, project.Language, creationInfo);
project.UpdateVisualStudioProjectProperties();
}
else
{
AssemblyName = project.AssemblyName,
FilePath = project.ProjectFilePath,
Hierarchy = project.Hierarchy,
ProjectGuid = project.Guid,
};
project.VisualStudioProject = _projectFactory.CreateAndAddToWorkspace(project.ProjectSystemName, project.Language, creationInfo);
project.UpdateVisualStudioProjectProperties();

_typeScriptProjects[project.Id] = project;
// We don't have an ID, so make something up
project.ExplicitId = ProjectId.CreateNewId(project.ProjectSystemName);
Workspace.OnProjectAdded(ProjectInfo.Create(project.ExplicitId, VersionStamp.Create(), project.ProjectSystemName, project.ProjectSystemName, project.Language));
}

_projects[project.Id] = project;
}

[Obsolete("This is a compatibility shim for TypeScript; please do not use it.")]
public bool ContainsProject(AbstractProject project)
{
// This will be set as long as the project has been added and not since removed
return project.VisualStudioProject != null;
return _projects.Values.Contains(project);
}

[Obsolete("This is a compatibility shim for TypeScript; please do not use it.")]
public void RemoveProject(AbstractProject project)
{
_typeScriptProjects.Remove(project.Id);
_projects.Remove(project.Id);

project.VisualStudioProject.RemoveFromWorkspace();
project.VisualStudioProject = null;
if (project.ExplicitId != null)
{
Workspace.OnProjectRemoved(project.ExplicitId);
}
else
{
project.VisualStudioProject.RemoveFromWorkspace();
project.VisualStudioProject = null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1288,18 +1288,29 @@ public void ApplyBatchChangeToProject(ProjectId projectId, Func<CodeAnalysis.Sol
}
}

private Dictionary<ProjectId, ProjectReferenceInformation> _projectReferenceInfo = new Dictionary<ProjectId, ProjectReferenceInformation>();
private Dictionary<ProjectId, ProjectReferenceInformation> _projectReferenceInfoMap = new Dictionary<ProjectId, ProjectReferenceInformation>();

private ProjectReferenceInformation GetReferenceInfo_NoLock(ProjectId projectId)
{
return _projectReferenceInfo.GetOrAdd(projectId, _ => new ProjectReferenceInformation());
return _projectReferenceInfoMap.GetOrAdd(projectId, _ => new ProjectReferenceInformation());
}

protected internal override void OnProjectRemoved(ProjectId projectId)
{
lock (_gate)
{
_projectReferenceInfo.Remove(projectId);
if (_projectReferenceInfoMap.TryGetValue(projectId, out var projectReferenceInfo))
{
// If we still had any output paths, we'll want to remove them to cause conversion back to metadata references.
// The call below implicitly is modifying the collection we've fetched, so we'll make a copy.
foreach (var outputPath in projectReferenceInfo.OutputPaths.ToList())
{
RemoveProjectOutputPath(projectId, outputPath);
}

_projectReferenceInfoMap.Remove(projectId);
}

_projectToGuidMap = _projectToGuidMap.Remove(projectId);
_projectToHierarchyMap = _projectToHierarchyMap.Remove(projectId);

Expand Down Expand Up @@ -1390,6 +1401,11 @@ private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId proje
SetSolutionAndRaiseWorkspaceChanged_NoLock(modifiedSolution, projectIdsChanged);
}

/// <summary>
/// Finds all projects that had a project reference to <paramref name="projectId"/> and convert it back to a metadata reference.
/// </summary>
/// <param name="projectId">The <see cref="ProjectId"/> of the project being referenced.</param>
/// <param name="outputPath">The output path of the given project to remove the link to.</param>
private void ConvertProjectReferencesToMetadataReferences_NoLock(ProjectId projectId, string outputPath)
{
var modifiedSolution = this.CurrentSolution;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static ContainedDocument TryGetContainedDocument(DocumentId id)
}

private readonly IComponentModel _componentModel;
private readonly VisualStudioWorkspace _workspace;
private readonly Workspace _workspace;
private readonly ITextDifferencingSelectorService _differenceSelectorService;
private readonly HostType _hostType;
private readonly ReiteratedVersionSnapshotTracker _snapshotTracker;
Expand All @@ -89,7 +89,7 @@ public ContainedDocument(
ITextBuffer subjectBuffer,
ITextBuffer dataBuffer,
IVsTextBufferCoordinator bufferCoordinator,
VisualStudioWorkspace workspace,
Workspace workspace,
VisualStudioProject project,
IVsHierarchy hierarchy,
uint itemId,
Expand Down Expand Up @@ -179,7 +179,8 @@ public void Dispose()

public DocumentId FindProjectDocumentIdWithItemId(uint itemidInsertionPoint)
{
var hierarchy = _workspace.GetHierarchy(_project.Id);
// We cast to VisualStudioWorkspace because the expectation is this isn't being used in Live Share workspaces
var hierarchy = ((VisualStudioWorkspace)_workspace).GetHierarchy(_project.Id);

foreach (var document in _workspace.CurrentSolution.GetProject(_project.Id).Documents)
{
Expand All @@ -194,7 +195,8 @@ public DocumentId FindProjectDocumentIdWithItemId(uint itemidInsertionPoint)

public uint FindItemIdOfDocument(Document document)
{
var hierarchy = _workspace.GetHierarchy(_project.Id);
// We cast to VisualStudioWorkspace because the expectation is this isn't being used in Live Share workspaces
var hierarchy = ((VisualStudioWorkspace)_workspace).GetHierarchy(_project.Id);
return hierarchy.TryGetItemId(_workspace.CurrentSolution.GetDocument(document.Id).FilePath);
}

Expand Down
Loading

0 comments on commit ce16eef

Please sign in to comment.