提交 146532ec 编写于 作者: M mattwar

Add implementation to support workspaces that want to enable adding/removing...

Add implementation to support workspaces that want to enable adding/removing projects and changing options duringTryApplyChanges (such as CustomWorkspace).
 (changeset 1393845)
上级 bdfe12d0
...@@ -18,6 +18,8 @@ public enum ApplyChangesKind ...@@ -18,6 +18,8 @@ public enum ApplyChangesKind
RemoveAnalyzerReference = 10, RemoveAnalyzerReference = 10,
AddAdditionalDocument = 11, AddAdditionalDocument = 11,
RemoveAdditionalDocument = 12, RemoveAdditionalDocument = 12,
ChangeAdditionalDocument = 13 ChangeAdditionalDocument = 13,
ChangeCompilationOptions = 14,
ChangeParseOptions = 15
} }
} }
\ No newline at end of file
...@@ -66,7 +66,7 @@ public Project AddProject(string name, string language) ...@@ -66,7 +66,7 @@ public Project AddProject(string name, string language)
/// <summary> /// <summary>
/// Adds a project to the workspace. All previous projects remain intact. /// Adds a project to the workspace. All previous projects remain intact.
/// </summary> /// </summary>
public Project AddProject(ProjectInfo projectInfo) public new Project AddProject(ProjectInfo projectInfo)
{ {
if (projectInfo == null) if (projectInfo == null)
{ {
......
...@@ -855,12 +855,24 @@ public virtual bool TryApplyChanges(Solution newSolution) ...@@ -855,12 +855,24 @@ public virtual bool TryApplyChanges(Solution newSolution)
var solutionWithLinkedFileChangesMerged = newSolution.WithMergedLinkedFileChangesAsync(oldSolution, solutionChanges, cancellationToken: CancellationToken.None).Result; var solutionWithLinkedFileChangesMerged = newSolution.WithMergedLinkedFileChangesAsync(oldSolution, solutionChanges, cancellationToken: CancellationToken.None).Result;
solutionChanges = solutionWithLinkedFileChangesMerged.GetChanges(oldSolution); solutionChanges = solutionWithLinkedFileChangesMerged.GetChanges(oldSolution);
// process all project changes // added projects
foreach (var proj in solutionChanges.GetAddedProjects())
{
this.AddProject(this.CreateProjectInfo(proj));
}
// changed projects
foreach (var projectChanges in solutionChanges.GetProjectChanges()) foreach (var projectChanges in solutionChanges.GetProjectChanges())
{ {
this.ApplyProjectChanges(projectChanges); this.ApplyProjectChanges(projectChanges);
} }
// removed projects
foreach (var proj in solutionChanges.GetRemovedProjects())
{
this.RemoveProject(proj.Id);
}
return true; return true;
} }
} }
...@@ -885,6 +897,18 @@ private void CheckAllowedSolutionChanges(SolutionChanges solutionChanges) ...@@ -885,6 +897,18 @@ private void CheckAllowedSolutionChanges(SolutionChanges solutionChanges)
private void CheckAllowedProjectChanges(ProjectChanges projectChanges) private void CheckAllowedProjectChanges(ProjectChanges projectChanges)
{ {
if (projectChanges.OldProject.CompilationOptions != projectChanges.NewProject.CompilationOptions
&& !this.CanApplyChange(ApplyChangesKind.ChangeCompilationOptions))
{
throw new NotSupportedException(WorkspacesResources.ChangingCompilationOptionsNotSupported);
}
if (projectChanges.OldProject.ParseOptions != projectChanges.NewProject.ParseOptions
&& !this.CanApplyChange(ApplyChangesKind.ChangeParseOptions))
{
throw new NotSupportedException(WorkspacesResources.ChangingParseOptionsNotSupported);
}
if (projectChanges.GetAddedDocuments().Any() && !this.CanApplyChange(ApplyChangesKind.AddDocument)) if (projectChanges.GetAddedDocuments().Any() && !this.CanApplyChange(ApplyChangesKind.AddDocument))
{ {
throw new NotSupportedException(WorkspacesResources.AddingDocumentsNotSupported); throw new NotSupportedException(WorkspacesResources.AddingDocumentsNotSupported);
...@@ -953,6 +977,18 @@ private void CheckAllowedProjectChanges(ProjectChanges projectChanges) ...@@ -953,6 +977,18 @@ private void CheckAllowedProjectChanges(ProjectChanges projectChanges)
/// </summary> /// </summary>
protected virtual void ApplyProjectChanges(ProjectChanges projectChanges) protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
{ {
// changed compilation options
if (projectChanges.OldProject.CompilationOptions != projectChanges.NewProject.CompilationOptions)
{
this.ChangeCompilationOptions(projectChanges.ProjectId, projectChanges.NewProject.CompilationOptions);
}
// changed parse options
if (projectChanges.OldProject.ParseOptions != projectChanges.NewProject.ParseOptions)
{
this.ChangeParseOptions(projectChanges.ProjectId, projectChanges.NewProject.ParseOptions);
}
// removed project references // removed project references
foreach (var removedProjectReference in projectChanges.GetRemovedProjectReferences()) foreach (var removedProjectReference in projectChanges.GetRemovedProjectReferences())
{ {
...@@ -1005,24 +1041,17 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges) ...@@ -1005,24 +1041,17 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
foreach (var documentId in projectChanges.GetAddedDocuments()) foreach (var documentId in projectChanges.GetAddedDocuments())
{ {
var doc = projectChanges.NewProject.GetDocument(documentId); var doc = projectChanges.NewProject.GetDocument(documentId);
var text = doc.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); // needs wait var text = this.GetTextForced(doc);
var info = DocumentInfo.Create( var info = this.CreateDocumentInfoWithoutText(doc);
documentId,
doc.Name,
doc.Folders,
doc.SourceCodeKind);
this.AddDocument(info, text); this.AddDocument(info, text);
} }
// added documents // added additional documents
foreach (var documentId in projectChanges.GetAddedAdditionalDocuments()) foreach (var documentId in projectChanges.GetAddedAdditionalDocuments())
{ {
var doc = projectChanges.NewProject.GetAdditionalDocument(documentId); var doc = projectChanges.NewProject.GetAdditionalDocument(documentId);
var text = doc.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); // needs wait var text = this.GetTextForced(doc);
var info = DocumentInfo.Create( var info = this.CreateDocumentInfoWithoutText(doc);
documentId,
doc.Name,
doc.Folders);
this.AddAdditionalDocument(info, text); this.AddAdditionalDocument(info, text);
} }
...@@ -1077,6 +1106,90 @@ private void CheckNoChanges(Solution oldSolution, Solution newSolution) ...@@ -1077,6 +1106,90 @@ private void CheckNoChanges(Solution oldSolution, Solution newSolution)
Contract.ThrowIfTrue(changes.GetProjectChanges().Any()); Contract.ThrowIfTrue(changes.GetProjectChanges().Any());
} }
private ProjectInfo CreateProjectInfo(Project project)
{
return ProjectInfo.Create(
project.Id,
VersionStamp.Create(),
project.Name,
project.AssemblyName,
project.Language,
project.FilePath,
project.OutputFilePath,
project.CompilationOptions,
project.ParseOptions,
project.Documents.Select(d => CreateDocumentInfoWithText(d)),
project.ProjectReferences,
project.MetadataReferences,
project.AnalyzerReferences,
project.AdditionalDocuments.Select(d => CreateDocumentInfoWithText(d)));
}
private SourceText GetTextForced(TextDocument doc)
{
return doc.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); // needs wait (called during TryApplyChanges)
}
private DocumentInfo CreateDocumentInfoWithText(TextDocument doc)
{
return CreateDocumentInfoWithoutText(doc).WithTextLoader(TextLoader.From(TextAndVersion.Create(GetTextForced(doc), VersionStamp.Create(), doc.FilePath)));
}
private DocumentInfo CreateDocumentInfoWithoutText(TextDocument doc)
{
var sourceDoc = doc as Document;
return DocumentInfo.Create(
doc.Id,
doc.Name,
doc.Folders,
sourceDoc != null ? sourceDoc.SourceCodeKind : SourceCodeKind.Regular,
filePath: doc.FilePath);
}
/// <summary>
/// This method is called during <see cref="TryApplyChanges"/> to add a project to the current solution.
///
/// Override this method to implement the capability of adding projects.
/// </summary>
protected virtual void AddProject(ProjectInfo project)
{
Debug.Assert(CanApplyChange(ApplyChangesKind.AddProject));
this.OnProjectAdded(project);
}
/// <summary>
/// This method is called during <see cref="TryApplyChanges"/> to remove a project from the current solution.
///
/// Override this method to implement the capability of removing projects.
/// </summary>
protected virtual void RemoveProject(ProjectId projectId)
{
Debug.Assert(CanApplyChange(ApplyChangesKind.RemoveProject));
this.OnProjectRemoved(projectId);
}
/// <summary>
/// This method is called during <see cref="TryApplyChanges"/> to change the compilation options.
///
/// Override this method to implement the capability of changing compilation options.
/// </summary>
protected virtual void ChangeCompilationOptions(ProjectId projectId, CompilationOptions options)
{
Debug.Assert(CanApplyChange(ApplyChangesKind.ChangeCompilationOptions));
this.OnCompilationOptionsChanged(projectId, options);
}
/// <summary>
/// This method is called during <see cref="TryApplyChanges"/> to change the parse options.
///
/// Override this method to implement the capability of changing parse options.
/// </summary>
protected virtual void ChangeParseOptions(ProjectId projectId, ParseOptions options)
{
Debug.Assert(CanApplyChange(ApplyChangesKind.ChangeParseOptions));
this.OnParseOptionsChanged(projectId, options);
}
/// <summary> /// <summary>
/// This method is called during <see cref="TryApplyChanges"/> to add a project reference to a project. /// This method is called during <see cref="TryApplyChanges"/> to add a project reference to a project.
/// ///
......
...@@ -250,6 +250,15 @@ internal class WorkspacesResources { ...@@ -250,6 +250,15 @@ internal class WorkspacesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Changing compilation options is not supported..
/// </summary>
internal static string ChangingCompilationOptionsNotSupported {
get {
return ResourceManager.GetString("ChangingCompilationOptionsNotSupported", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Changing documents is not supported.. /// Looks up a localized string similar to Changing documents is not supported..
/// </summary> /// </summary>
...@@ -259,6 +268,15 @@ internal class WorkspacesResources { ...@@ -259,6 +268,15 @@ internal class WorkspacesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Changing parse options is not supported..
/// </summary>
internal static string ChangingParseOptionsNotSupported {
get {
return ResourceManager.GetString("ChangingParseOptionsNotSupported", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Changing project properties is not supported.. /// Looks up a localized string similar to Changing project properties is not supported..
/// </summary> /// </summary>
......
...@@ -441,4 +441,10 @@ ...@@ -441,4 +441,10 @@
<data name="TheSymbolCannotBeLocatedWithinTheCurrentSolution" xml:space="preserve"> <data name="TheSymbolCannotBeLocatedWithinTheCurrentSolution" xml:space="preserve">
<value>The symbol '{0}' cannot be located within the current solution.</value> <value>The symbol '{0}' cannot be located within the current solution.</value>
</data> </data>
<data name="ChangingCompilationOptionsNotSupported" xml:space="preserve">
<value>Changing compilation options is not supported.</value>
</data>
<data name="ChangingParseOptionsNotSupported" xml:space="preserve">
<value>Changing parse options is not supported.</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -178,5 +178,72 @@ public void TestAddProject_CommandLineProject() ...@@ -178,5 +178,72 @@ public void TestAddProject_CommandLineProject()
var compilation = project.GetCompilationAsync().Result; var compilation = project.GetCompilationAsync().Result;
} }
} }
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
public void TestAddProject_TryApplyChanges()
{
using (var ws = new CustomWorkspace())
{
ProjectId pid = ProjectId.CreateNewId();
var docInfo = DocumentInfo.Create(
DocumentId.CreateNewId(pid),
"MyDoc.cs",
loader: TextLoader.From(TextAndVersion.Create(SourceText.From(""), VersionStamp.Create())));
var projInfo = ProjectInfo.Create(
pid,
VersionStamp.Create(),
"NewProject",
"NewProject.dll",
LanguageNames.CSharp,
documents: new[] { docInfo });
var newSolution = ws.CurrentSolution.AddProject(projInfo);
Assert.Equal(0, ws.CurrentSolution.Projects.Count());
var result = ws.TryApplyChanges(newSolution);
Assert.Equal(result, true);
Assert.Equal(1, ws.CurrentSolution.Projects.Count());
var proj = ws.CurrentSolution.Projects.First();
Assert.Equal("NewProject", proj.Name);
Assert.Equal("NewProject.dll", proj.AssemblyName);
Assert.Equal(LanguageNames.CSharp, proj.Language);
Assert.Equal(1, proj.Documents.Count());
var doc = proj.Documents.First();
Assert.Equal("MyDoc.cs", doc.Name);
}
}
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
public void TestRemoveProject_TryApplyChanges()
{
var pid = ProjectId.CreateNewId();
var info = ProjectInfo.Create(
pid,
version: VersionStamp.Default,
name: "TestProject",
assemblyName: "TestProject.dll",
language: LanguageNames.CSharp);
using (var ws = new CustomWorkspace())
{
ws.AddProject(info);
Assert.Equal(1, ws.CurrentSolution.Projects.Count());
var newSolution = ws.CurrentSolution.RemoveProject(pid);
Assert.Equal(0, newSolution.Projects.Count());
var result = ws.TryApplyChanges(newSolution);
Assert.Equal(true, result);
Assert.Equal(0, ws.CurrentSolution.Projects.Count());
}
}
} }
} }
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册