提交 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
RemoveAnalyzerReference = 10,
AddAdditionalDocument = 11,
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)
/// <summary>
/// Adds a project to the workspace. All previous projects remain intact.
/// </summary>
public Project AddProject(ProjectInfo projectInfo)
public new Project AddProject(ProjectInfo projectInfo)
{
if (projectInfo == null)
{
......
......@@ -855,12 +855,24 @@ public virtual bool TryApplyChanges(Solution newSolution)
var solutionWithLinkedFileChangesMerged = newSolution.WithMergedLinkedFileChangesAsync(oldSolution, solutionChanges, cancellationToken: CancellationToken.None).Result;
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())
{
this.ApplyProjectChanges(projectChanges);
}
// removed projects
foreach (var proj in solutionChanges.GetRemovedProjects())
{
this.RemoveProject(proj.Id);
}
return true;
}
}
......@@ -885,6 +897,18 @@ private void CheckAllowedSolutionChanges(SolutionChanges solutionChanges)
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))
{
throw new NotSupportedException(WorkspacesResources.AddingDocumentsNotSupported);
......@@ -953,6 +977,18 @@ private void CheckAllowedProjectChanges(ProjectChanges projectChanges)
/// </summary>
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
foreach (var removedProjectReference in projectChanges.GetRemovedProjectReferences())
{
......@@ -1005,24 +1041,17 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
foreach (var documentId in projectChanges.GetAddedDocuments())
{
var doc = projectChanges.NewProject.GetDocument(documentId);
var text = doc.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); // needs wait
var info = DocumentInfo.Create(
documentId,
doc.Name,
doc.Folders,
doc.SourceCodeKind);
var text = this.GetTextForced(doc);
var info = this.CreateDocumentInfoWithoutText(doc);
this.AddDocument(info, text);
}
// added documents
// added additional documents
foreach (var documentId in projectChanges.GetAddedAdditionalDocuments())
{
var doc = projectChanges.NewProject.GetAdditionalDocument(documentId);
var text = doc.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); // needs wait
var info = DocumentInfo.Create(
documentId,
doc.Name,
doc.Folders);
var text = this.GetTextForced(doc);
var info = this.CreateDocumentInfoWithoutText(doc);
this.AddAdditionalDocument(info, text);
}
......@@ -1077,6 +1106,90 @@ private void CheckNoChanges(Solution oldSolution, Solution newSolution)
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>
/// This method is called during <see cref="TryApplyChanges"/> to add a project reference to a project.
///
......
......@@ -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>
/// Looks up a localized string similar to Changing documents is not supported..
/// </summary>
......@@ -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>
/// Looks up a localized string similar to Changing project properties is not supported..
/// </summary>
......
......@@ -441,4 +441,10 @@
<data name="TheSymbolCannotBeLocatedWithinTheCurrentSolution" xml:space="preserve">
<value>The symbol '{0}' cannot be located within the current solution.</value>
</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>
\ No newline at end of file
......@@ -178,5 +178,72 @@ public void TestAddProject_CommandLineProject()
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.
先完成此消息的编辑!
想要评论请 注册