Skip to content

Commit 6f09af8

Browse files
authored
Merge pull request #36311 from sharwell/cleanup-documents
Implement code cleanup for documents
2 parents 2a98d64 + fc8e91d commit 6f09af8

File tree

1 file changed

+48
-26
lines changed

1 file changed

+48
-26
lines changed

src/VisualStudio/CSharp/Impl/LanguageService/CSharpCodeCleanupFixer.cs

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Immutable;
55
using System.ComponentModel.Composition;
66
using System.IO;
7+
using System.Linq;
78
using System.Threading;
89
using System.Threading.Tasks;
910
using Microsoft.CodeAnalysis;
@@ -70,34 +71,34 @@ private async Task<bool> FixHierarchyContentAsync(IVsHierarchyCodeCleanupScope h
7071
return await FixSolutionAsync(_workspace.CurrentSolution, context).ConfigureAwait(true);
7172
}
7273

73-
var itemId = hierarchyContent.ItemId;
74-
if (itemId == (uint)VSConstants.VSITEMID.Root)
74+
// Map the hierarchy to a ProjectId. For hierarchies mapping to multitargeted projects, we first try to
75+
// get the project in the most recent active context, but fall back to the first target framework if no
76+
// active context is available.
77+
var hierarchyToProjectMap = _workspace.Services.GetRequiredService<IHierarchyItemToProjectIdMap>();
78+
79+
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(context.OperationContext.UserCancellationToken);
80+
context.OperationContext.UserCancellationToken.ThrowIfCancellationRequested();
81+
82+
ProjectId projectId = null;
83+
if (ErrorHandler.Succeeded(hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID8.VSHPROPID_ActiveIntellisenseProjectContext, out var contextProjectNameObject))
84+
&& contextProjectNameObject is string contextProjectName
85+
&& hierarchy.TryGetProjectGuid(out var projectGuid))
7586
{
76-
// Map the hierarchy to a ProjectId. For hierarchies mapping to multitargeted projects, we first try to
77-
// get the project in the most recent active context, but fall back to the first target framework if no
78-
// active context is available.
79-
var hierarchyToProjectMap = _workspace.Services.GetRequiredService<IHierarchyItemToProjectIdMap>();
80-
81-
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(context.OperationContext.UserCancellationToken);
82-
context.OperationContext.UserCancellationToken.ThrowIfCancellationRequested();
83-
84-
ProjectId projectId = null;
85-
if (ErrorHandler.Succeeded(hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID8.VSHPROPID_ActiveIntellisenseProjectContext, out var contextProjectNameObject))
86-
&& contextProjectNameObject is string contextProjectName
87-
&& hierarchy.TryGetProjectGuid(out var projectGuid))
88-
{
89-
projectId = _workspace.GetProjectWithGuidAndName(projectGuid, contextProjectName)?.Id;
90-
}
87+
projectId = _workspace.GetProjectWithGuidAndName(projectGuid, contextProjectName)?.Id;
88+
}
9189

92-
if (projectId is null)
90+
if (projectId is null)
91+
{
92+
var projectHierarchyItem = _vsHierarchyItemManager.GetHierarchyItem(hierarchyContent.Hierarchy, (uint)VSConstants.VSITEMID.Root);
93+
if (!hierarchyToProjectMap.TryGetProjectId(projectHierarchyItem, targetFrameworkMoniker: null, out projectId))
9394
{
94-
var projectHierarchyItem = _vsHierarchyItemManager.GetHierarchyItem(hierarchyContent.Hierarchy, itemId);
95-
if (!hierarchyToProjectMap.TryGetProjectId(projectHierarchyItem, targetFrameworkMoniker: null, out projectId))
96-
{
97-
return false;
98-
}
95+
return false;
9996
}
97+
}
10098

99+
var itemId = hierarchyContent.ItemId;
100+
if (itemId == (uint)VSConstants.VSITEMID.Root)
101+
{
101102
await TaskScheduler.Default;
102103

103104
var project = _workspace.CurrentSolution.GetProject(projectId);
@@ -119,9 +120,18 @@ private async Task<bool> FixHierarchyContentAsync(IVsHierarchyCodeCleanupScope h
119120
}
120121
else
121122
{
122-
// document
123-
// TODO: this one will be implemented later
124-
// https://github.com/dotnet/roslyn/issues/30165
123+
// Handle code cleanup for a single document
124+
await TaskScheduler.Default;
125+
126+
var solution = _workspace.CurrentSolution;
127+
var documentIds = solution.GetDocumentIdsWithFilePath(path);
128+
var documentId = documentIds.FirstOrDefault(id => id.ProjectId == projectId);
129+
if (documentId is null)
130+
{
131+
return false;
132+
}
133+
134+
return await FixDocumentAsync(solution.GetDocument(documentId), context).ConfigureAwait(true);
125135
}
126136
}
127137

@@ -152,6 +162,18 @@ async Task<Solution> ApplyFixAsync(ProgressTracker progressTracker, Cancellation
152162
}
153163
}
154164

165+
private Task<bool> FixDocumentAsync(Document document, ICodeCleanUpExecutionContext context)
166+
{
167+
return FixAsync(document.Project.Solution.Workspace, ApplyFixAsync, context, document.Name);
168+
169+
// Local function
170+
async Task<Solution> ApplyFixAsync(ProgressTracker progressTracker, CancellationToken cancellationToken)
171+
{
172+
var newDocument = await FixDocumentAsync(document, context.EnabledFixIds, progressTracker, cancellationToken).ConfigureAwait(true);
173+
return newDocument.Project.Solution;
174+
}
175+
}
176+
155177
private Task<bool> FixTextBufferAsync(TextBufferCodeCleanUpScope textBufferScope, ICodeCleanUpExecutionContext context)
156178
{
157179
var buffer = textBufferScope.SubjectBuffer;

0 commit comments

Comments
 (0)