Skip to content

Commit 4a4c96f

Browse files
committed
Use syntax generator
Insane bloat
1 parent 0e0d578 commit 4a4c96f

2 files changed

Lines changed: 100 additions & 16 deletions

File tree

WpfAnalyzers.Test/ImplementValueConverterFixTests/CodeFix.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,44 @@ object IValueConverter.ConvertBack(object value, System.Type targetType, object
4747
RoslynAssert.CodeFix(Fix, ExpectedDiagnostic, before, after);
4848
}
4949

50+
[Test]
51+
public static void IValueConverterConvertBackFileScopedNamespace()
52+
{
53+
var before = @"
54+
namespace N;
55+
56+
using System.Windows.Data;
57+
58+
public class C : ↓IValueConverter
59+
{
60+
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
61+
{
62+
throw new System.NotImplementedException();
63+
}
64+
}
65+
";
66+
67+
var after = @"
68+
namespace N;
69+
70+
using System.Windows.Data;
71+
72+
public class C : IValueConverter
73+
{
74+
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
75+
{
76+
throw new System.NotImplementedException();
77+
}
78+
79+
object IValueConverter.ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
80+
{
81+
throw new System.NotSupportedException($""{nameof(C)} can only be used in OneWay bindings"");
82+
}
83+
}
84+
";
85+
RoslynAssert.CodeFix(Fix, ExpectedDiagnostic, before, after);
86+
}
87+
5088
[Test]
5189
public static void IMultiValueConverterConvertBack()
5290
{

WpfAnalyzers/CodeFixes/ImplementValueConverterFix.cs

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,20 @@ namespace WpfAnalyzers;
55
using System.Composition;
66
using System.Globalization;
77
using System.Threading.Tasks;
8+
89
using Gu.Roslyn.AnalyzerExtensions;
910
using Gu.Roslyn.CodeFixExtensions;
11+
1012
using Microsoft.CodeAnalysis;
1113
using Microsoft.CodeAnalysis.CodeFixes;
1214
using Microsoft.CodeAnalysis.CSharp;
1315
using Microsoft.CodeAnalysis.CSharp.Syntax;
16+
using Microsoft.CodeAnalysis.Editing;
1417

1518
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ImplementValueConverterFix))]
1619
[Shared]
1720
internal class ImplementValueConverterFix : DocumentEditorCodeFixProvider
1821
{
19-
private static readonly MethodDeclarationSyntax IValueConverterConvert = ParseMethod(
20-
@" public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
21-
{
22-
throw new System.NotImplementedException();
23-
}");
24-
2522
private static readonly MethodDeclarationSyntax IMultiValueConverterConvert = ParseMethod(
2623
@" public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
2724
{
@@ -47,7 +44,7 @@ protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContex
4744
{
4845
context.RegisterCodeFix(
4946
"Implement IValueConverter.Convert for one way bindings.",
50-
(editor, _) => editor.AddMethod(classDeclaration, IValueConverterConvert),
47+
(editor, _) => editor.AddMethod(classDeclaration, Convert(editor.Generator)),
5148
"Implement IValueConverter",
5249
diagnostic);
5350
}
@@ -57,7 +54,7 @@ protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContex
5754
{
5855
context.RegisterCodeFix(
5956
"Implement IValueConverter.ConvertBack for one way bindings.",
60-
(editor, _) => editor.AddMethod(classDeclaration, IValueConverterConvertBack(classDeclaration.Identifier.ValueText)),
57+
(editor, _) => editor.AddMethod(classDeclaration, ConvertBack(editor.Generator, classDeclaration.Identifier.ValueText)),
6158
"Implement IValueConverter",
6259
diagnostic);
6360
}
@@ -109,15 +106,64 @@ private static bool HasInterface(ClassDeclarationSyntax classDeclaration, Qualif
109106
return false;
110107
}
111108

112-
private static MethodDeclarationSyntax IValueConverterConvertBack(string containingTypeName)
109+
private static MethodDeclarationSyntax Convert(SyntaxGenerator generator)
113110
{
114-
var code = StringBuilderPool.Borrow()
115-
.AppendLine(" object System.Windows.Data.IValueConverter.ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)")
116-
.AppendLine(" {")
117-
.AppendLine($" throw new System.NotSupportedException($\"{{nameof({containingTypeName})}} can only be used in OneWay bindings\");")
118-
.AppendLine(" }")
119-
.Return();
120-
return ParseMethod(code);
111+
return (MethodDeclarationSyntax)generator.MethodDeclaration(
112+
accessibility: Accessibility.Public,
113+
returnType: SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword)),
114+
name: "Convert",
115+
parameters: new[]
116+
{
117+
generator.ParameterDeclaration("value", SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword))),
118+
generator.ParameterDeclaration("targetType", SyntaxFactory.ParseTypeName("System.Type").WithSimplifiedNames()),
119+
generator.ParameterDeclaration("parameter", SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword))),
120+
generator.ParameterDeclaration("culture", SyntaxFactory.ParseTypeName("System.Globalization.CultureInfo").WithSimplifiedNames()),
121+
},
122+
statements: new[] { generator.ThrowStatement(generator.ObjectCreationExpression(SyntaxFactory.ParseTypeName("System.NotImplementedException").WithSimplifiedNames())) });
123+
}
124+
125+
private static MethodDeclarationSyntax ConvertBack(SyntaxGenerator generator, string containingTypeName)
126+
{
127+
return ((MethodDeclarationSyntax)generator.MethodDeclaration(
128+
returnType: SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword)),
129+
name: "ConvertBack",
130+
parameters: new[]
131+
{
132+
generator.ParameterDeclaration("value", SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword))),
133+
generator.ParameterDeclaration("targetType", SyntaxFactory.ParseTypeName("System.Type").WithSimplifiedNames()),
134+
generator.ParameterDeclaration("parameter", SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword))),
135+
generator.ParameterDeclaration("culture", SyntaxFactory.ParseTypeName("System.Globalization.CultureInfo").WithSimplifiedNames()),
136+
},
137+
statements: new[] { Throw() }))
138+
.WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.ParseName("IValueConverter")));
139+
140+
ThrowStatementSyntax Throw()
141+
{
142+
return (ThrowStatementSyntax)generator.ThrowStatement(
143+
generator.ObjectCreationExpression(
144+
SyntaxFactory.ParseTypeName("System.NotSupportedException"),
145+
SyntaxFactory.Argument(
146+
expression: SyntaxFactory.InterpolatedStringExpression(
147+
stringStartToken: SyntaxFactory.Token(SyntaxKind.InterpolatedStringStartToken),
148+
contents: SyntaxFactory.List(
149+
new InterpolatedStringContentSyntax[]
150+
{
151+
SyntaxFactory.Interpolation(
152+
openBraceToken: SyntaxFactory.Token(SyntaxKind.OpenBraceToken),
153+
expression: (ExpressionSyntax)generator.NameOfExpression(SyntaxFactory.ParseTypeName(containingTypeName)),
154+
alignmentClause: default,
155+
formatClause: default,
156+
closeBraceToken: SyntaxFactory.Token(SyntaxKind.CloseBraceToken)),
157+
SyntaxFactory.InterpolatedStringText(
158+
textToken: SyntaxFactory.Token(
159+
leading: default,
160+
kind: SyntaxKind.InterpolatedStringTextToken,
161+
text: " can only be used in OneWay bindings",
162+
valueText: " can only be used in OneWay bindings",
163+
trailing: default)),
164+
}),
165+
stringEndToken: SyntaxFactory.Token(SyntaxKind.InterpolatedStringEndToken)))));
166+
}
121167
}
122168

123169
private static MethodDeclarationSyntax IMultiValueConverterConvertBack(string containingTypeName)

0 commit comments

Comments
 (0)