Skip to content

Commit 4452ff5

Browse files
committed
Add 'Generate additional part' refactoring
1 parent e6055ae commit 4452ff5

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
namespace StyleCop.Analyzers.PrivateCodeFixes;
5+
6+
using System.IO;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using Analyzer.Utilities;
10+
using Microsoft.CodeAnalysis;
11+
using Microsoft.CodeAnalysis.CodeActions;
12+
using Microsoft.CodeAnalysis.CodeRefactorings;
13+
using Microsoft.CodeAnalysis.CSharp;
14+
using Microsoft.CodeAnalysis.CSharp.Syntax;
15+
using Microsoft.CodeAnalysis.Text;
16+
17+
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(GeneratePartCodeRefactoringProvider))]
18+
internal sealed class GeneratePartCodeRefactoringProvider
19+
: CodeRefactoringProvider
20+
{
21+
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
22+
{
23+
var partialType = await context.TryGetRelevantNodeAsync<ClassDeclarationSyntax>(CSharpRefactoringHelpers.Instance).ConfigureAwait(false);
24+
if (partialType is not { Modifiers: var modifiers }
25+
|| !modifiers.Any(SyntaxKind.PartialKeyword))
26+
{
27+
return;
28+
}
29+
30+
context.RegisterRefactoring(CodeAction.Create(
31+
"Generate additional part",
32+
async cancellationToken =>
33+
{
34+
var namespaceDeclaration = partialType.FirstAncestorOrSelf<BaseNamespaceDeclarationSyntax>();
35+
if (namespaceDeclaration is null)
36+
{
37+
return context.Document.Project.Solution;
38+
}
39+
40+
var firstUsing = namespaceDeclaration.Usings.FirstOrDefault()?.Name.ToString();
41+
42+
var namespaceName = namespaceDeclaration.Name.ToString();
43+
var subNamespace = namespaceName;
44+
var rootNamespace = context.Document.Project.DefaultNamespace;
45+
if (!string.IsNullOrEmpty(rootNamespace) && namespaceName.StartsWith(rootNamespace + "."))
46+
{
47+
subNamespace = namespaceName[(rootNamespace.Length + 1)..];
48+
}
49+
50+
var content = $@"// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
51+
// Licensed under the MIT License. See LICENSE in the project root for license information.
52+
53+
namespace {namespaceName};
54+
55+
using {firstUsing};
56+
57+
public partial class {partialType.Identifier.ValueText} {partialType.BaseList}
58+
{{
59+
}}
60+
";
61+
62+
var fileName = partialType.Identifier.ValueText + ".cs";
63+
var directory = Path.GetDirectoryName(context.Document.Project.FilePath)!;
64+
var existingText = await context.Document.GetTextAsync(cancellationToken).ConfigureAwait(false);
65+
66+
var addedDocument = context.Document.Project.AddDocument(
67+
fileName,
68+
SourceText.From(content, new UTF8Encoding(true), existingText.ChecksumAlgorithm),
69+
folders: subNamespace.Split('.'),
70+
filePath: Path.Combine(directory, Path.Combine(subNamespace.Split('.')), fileName));
71+
72+
return addedDocument.Project.Solution;
73+
},
74+
nameof(GeneratePartCodeRefactoringProvider)));
75+
}
76+
}

0 commit comments

Comments
 (0)