Skip to content

Commit 7c3cc17

Browse files
VS-106: Refactor out SyntaxElements in TemplateBuilders (#86)
* VS-106: Refactor out SyntaxElements in TemplateBuilders --------- Co-authored-by: Ravi Raghavan <[email protected]>
1 parent e116a40 commit 7c3cc17

8 files changed

+74
-70
lines changed

Diff for: src/MongoDB.Analyzer/AnalyzerReleases.Shipped.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Rule ID | Category | Severity | Notes
1919
MAPoco1001 | MongoDB.Analyzer.Poco | Info | Poco to Json [Documentation](https://www.mongodb.com/docs/mongodb-analyzer/current/rules/#mapoco1001)
2020
MAPoco2001 | MongoDB.Analyzer.Poco | Warning | Unsupported POCO [Documentation](https://www.mongodb.com/docs/mongodb-analyzer/current/rules/#mapoco2001)
2121

22-
## Release 1.4.0
22+
## Release 1.5.0
2323

2424
### New Rules
2525

Diff for: src/MongoDB.Analyzer/Core/Builders/AnalysisCodeGenerator.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ namespace MongoDB.Analyzer.Core.Builders;
2020

2121
internal static class AnalysisCodeGenerator
2222
{
23-
private static readonly BuildersMqlGeneratorTemplateBuilder.SyntaxElements s_mqlGeneratorSyntaxElements;
23+
private static readonly MqlGeneratorTestMethodTemplate s_testMethodTemplate;
2424
private static readonly CSharpParseOptions s_parseOptions;
2525
private static readonly SyntaxTreesCache s_syntaxTreesCache;
2626

2727
static AnalysisCodeGenerator()
2828
{
2929
var mqlGeneratorSyntaxTree = GetCodeResource(ResourceNames.Builders.MqlGenerator);
30-
s_mqlGeneratorSyntaxElements = BuildersMqlGeneratorTemplateBuilder.CreateSyntaxElements(mqlGeneratorSyntaxTree);
30+
s_testMethodTemplate = BuildersMqlGeneratorTemplateBuilder.CreateTestMethodTemplate(mqlGeneratorSyntaxTree);
3131

3232
s_parseOptions = (CSharpParseOptions)mqlGeneratorSyntaxTree.Options;
3333
s_syntaxTreesCache = new SyntaxTreesCache(s_parseOptions, ResourceNames.Builders.Renderer);
@@ -68,7 +68,7 @@ public static CompilationResult Compile(MongoAnalysisContext context, Expression
6868

6969
private static SyntaxTree GenerateMqlGeneratorSyntaxTree(ExpressionsAnalysis builderExpressionAnalysis)
7070
{
71-
var testCodeBuilder = new BuildersMqlGeneratorTemplateBuilder(s_mqlGeneratorSyntaxElements);
71+
var testCodeBuilder = new BuildersMqlGeneratorTemplateBuilder(s_testMethodTemplate);
7272
var generatedMqlMethodDeclarations = new List<MethodDeclarationSyntax>(builderExpressionAnalysis.AnalysisNodeContexts.Length);
7373

7474
foreach (var builderContext in builderExpressionAnalysis.AnalysisNodeContexts)

Diff for: src/MongoDB.Analyzer/Core/Builders/BuildersMqlGeneratorTemplateBuilder.cs

+12-21
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,27 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using MongoDB.Analyzer.Core.Utilities;
1516
using static MongoDB.Analyzer.Core.HelperResources.MqlGeneratorSyntaxElements.Builders;
1617

1718
namespace MongoDB.Analyzer.Core.Builders;
1819

1920
internal sealed class BuildersMqlGeneratorTemplateBuilder
2021
{
21-
internal record SyntaxElements(
22-
SyntaxNode Root,
23-
ClassDeclarationSyntax ClassDeclarationSyntax,
24-
MethodDeclarationSyntax TestMethodNode,
25-
SyntaxNode BuilderDefinitionNode,
26-
SyntaxNode CollectionTypeNode)
27-
{
28-
public SyntaxNode[] NodesToReplace { get; } = new[] { BuilderDefinitionNode, CollectionTypeNode };
29-
}
30-
3122
private ClassDeclarationSyntax _mqlGeneratorDeclarationSyntaxNew;
3223
private int _nextTestMethodIndex;
33-
private readonly SyntaxElements _syntaxElements;
24+
private readonly MqlGeneratorTestMethodTemplate _testMethodTemplate;
3425

35-
public BuildersMqlGeneratorTemplateBuilder(SyntaxElements syntaxElements)
26+
public BuildersMqlGeneratorTemplateBuilder(MqlGeneratorTestMethodTemplate testMethodTemplate)
3627
{
37-
_syntaxElements = syntaxElements;
38-
_mqlGeneratorDeclarationSyntaxNew = _syntaxElements.ClassDeclarationSyntax;
28+
_testMethodTemplate = testMethodTemplate;
29+
_mqlGeneratorDeclarationSyntaxNew = _testMethodTemplate.ClassDeclarationSyntax;
3930
}
4031

4132
public void AddMqlGeneratorMethods(MemberDeclarationSyntax[] methodDeclarations) =>
4233
_mqlGeneratorDeclarationSyntaxNew = _mqlGeneratorDeclarationSyntaxNew.AddMembers(methodDeclarations);
4334

44-
public static SyntaxElements CreateSyntaxElements(SyntaxTree mqlGeneratorSyntaxTree)
35+
public static MqlGeneratorTestMethodTemplate CreateTestMethodTemplate(SyntaxTree mqlGeneratorSyntaxTree)
4536
{
4637
var root = mqlGeneratorSyntaxTree.GetRoot();
4738

@@ -50,25 +41,25 @@ public static SyntaxElements CreateSyntaxElements(SyntaxTree mqlGeneratorSyntaxT
5041
var builderDefinitionNode = mainTestMethodNode.GetSingleIdentifier(FilterName).Parent.Parent;
5142
var collectionTypeNode = mainTestMethodNode.GetIdentifiers(MqlGeneratorTemplateType).ElementAt(0);
5243

53-
return new SyntaxElements(root, classDeclarationSyntax, mainTestMethodNode, builderDefinitionNode, collectionTypeNode);
44+
return new MqlGeneratorTestMethodTemplate(root, classDeclarationSyntax, mainTestMethodNode, builderDefinitionNode, collectionTypeNode, AnalysisType.Builders);
5445
}
5546

5647
public (string newMethodName, MethodDeclarationSyntax newMethodDeclaration) GenerateMqlGeneratorMethod(string typeArgumentName, SyntaxNode buildersExpression)
5748
{
58-
var newMethodDeclaration = _syntaxElements.TestMethodNode.ReplaceNodes(_syntaxElements.NodesToReplace, (n, _) =>
49+
var newMethodDeclaration = _testMethodTemplate.TestMethodNode.ReplaceNodes(_testMethodTemplate.NodesToReplace, (n, _) =>
5950
n switch
6051
{
61-
_ when n == _syntaxElements.BuilderDefinitionNode => buildersExpression,
62-
_ when n == _syntaxElements.CollectionTypeNode => SyntaxFactory.IdentifierName(typeArgumentName),
52+
_ when n == _testMethodTemplate.ExpressionNode => buildersExpression,
53+
_ when n == _testMethodTemplate.TypeNode => SyntaxFactory.IdentifierName(typeArgumentName),
6354
_ => throw new Exception($"Unrecognized node {n}")
6455
});
6556

66-
var newMqlGeneratorMethodName = $"{_syntaxElements.TestMethodNode.Identifier.Value}_{_nextTestMethodIndex++}";
57+
var newMqlGeneratorMethodName = $"{_testMethodTemplate.TestMethodNode.Identifier.Value}_{_nextTestMethodIndex++}";
6758
newMethodDeclaration = newMethodDeclaration.WithIdentifier(SyntaxFactory.Identifier(newMqlGeneratorMethodName));
6859

6960
return (newMqlGeneratorMethodName, newMethodDeclaration);
7061
}
7162

7263
public SyntaxTree GenerateSyntaxTree() =>
73-
_syntaxElements.Root.ReplaceNode(_syntaxElements.ClassDeclarationSyntax, _mqlGeneratorDeclarationSyntaxNew).SyntaxTree;
64+
_testMethodTemplate.Root.ReplaceNode(_testMethodTemplate.ClassDeclarationSyntax, _mqlGeneratorDeclarationSyntaxNew).SyntaxTree;
7465
}

Diff for: src/MongoDB.Analyzer/Core/Linq/AnalysisCodeGenerator.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ namespace MongoDB.Analyzer.Core.Linq;
2121
internal static class AnalysisCodeGenerator
2222
{
2323
private static readonly SyntaxTreesCache s_syntaxTreesCache;
24-
private static readonly LinqMqlGeneratorTemplateBuilder.SyntaxElements s_mqlGeneratorSyntaxElements;
24+
private static readonly MqlGeneratorTestMethodTemplate s_testMethodTemplate;
2525
private static readonly CSharpParseOptions s_parseOptions;
2626

2727
static AnalysisCodeGenerator()
2828
{
2929
var mqlGeneratorSyntaxTree = GetCodeResource(ResourceNames.Linq.MqlGenerator);
30-
s_mqlGeneratorSyntaxElements = LinqMqlGeneratorTemplateBuilder.CreateSyntaxElements(mqlGeneratorSyntaxTree);
30+
s_testMethodTemplate = LinqMqlGeneratorTemplateBuilder.CreateTestMethodTemplate(mqlGeneratorSyntaxTree);
3131

3232
s_parseOptions = (CSharpParseOptions)mqlGeneratorSyntaxTree.Options;
3333
s_syntaxTreesCache = new SyntaxTreesCache(s_parseOptions, ResourceNames.Linq.QueryableProvider);
@@ -72,7 +72,7 @@ public static CompilationResult Compile(MongoAnalysisContext context, Expression
7272

7373
private static SyntaxTree GenerateMqlGeneratorSyntaxTree(ExpressionsAnalysis linqExpressionAnalysis)
7474
{
75-
var testCodeBuilder = new LinqMqlGeneratorTemplateBuilder(s_mqlGeneratorSyntaxElements);
75+
var testCodeBuilder = new LinqMqlGeneratorTemplateBuilder(s_testMethodTemplate);
7676
var generatedMqlMethodDeclarations = new List<MethodDeclarationSyntax>(linqExpressionAnalysis.AnalysisNodeContexts.Length);
7777

7878
foreach (var linqContext in linqExpressionAnalysis.AnalysisNodeContexts)

Diff for: src/MongoDB.Analyzer/Core/Linq/LinqMqlGeneratorTemplateBuilder.cs

+12-21
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,27 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using MongoDB.Analyzer.Core.Utilities;
1516
using static MongoDB.Analyzer.Core.HelperResources.MqlGeneratorSyntaxElements.Linq;
1617

1718
namespace MongoDB.Analyzer.Core.Linq;
1819

1920
internal sealed class LinqMqlGeneratorTemplateBuilder
2021
{
21-
internal record SyntaxElements(
22-
SyntaxNode Root,
23-
ClassDeclarationSyntax ClassDeclarationSyntax,
24-
MethodDeclarationSyntax TestMethodNode,
25-
SyntaxNode LinqExpressionNode,
26-
SyntaxNode QueryableTypeNode)
27-
{
28-
public SyntaxNode[] NodesToReplace { get; } = new[] { LinqExpressionNode, QueryableTypeNode };
29-
}
30-
31-
private readonly SyntaxElements _syntaxElements;
22+
private readonly MqlGeneratorTestMethodTemplate _testMethodTemplate;
3223
private ClassDeclarationSyntax _mqlGeneratorDeclarationSyntaxNew;
3324
private int _nextTestMethodIndex;
3425

35-
public LinqMqlGeneratorTemplateBuilder(SyntaxElements syntaxElements)
26+
public LinqMqlGeneratorTemplateBuilder(MqlGeneratorTestMethodTemplate testMethodTemplate)
3627
{
37-
_syntaxElements = syntaxElements;
38-
_mqlGeneratorDeclarationSyntaxNew = _syntaxElements.ClassDeclarationSyntax;
28+
_testMethodTemplate = testMethodTemplate;
29+
_mqlGeneratorDeclarationSyntaxNew = _testMethodTemplate.ClassDeclarationSyntax;
3930
}
4031

4132
public void AddMqlGeneratorMethods(MemberDeclarationSyntax[] methodDeclarations) =>
4233
_mqlGeneratorDeclarationSyntaxNew = _mqlGeneratorDeclarationSyntaxNew.AddMembers(methodDeclarations);
4334

44-
public static SyntaxElements CreateSyntaxElements(SyntaxTree mqlGeneratorSyntaxTree)
35+
public static MqlGeneratorTestMethodTemplate CreateTestMethodTemplate(SyntaxTree mqlGeneratorSyntaxTree)
4536
{
4637
var root = mqlGeneratorSyntaxTree.GetRoot();
4738

@@ -50,25 +41,25 @@ public static SyntaxElements CreateSyntaxElements(SyntaxTree mqlGeneratorSyntaxT
5041
var queryableTypeNode = mainTestMethodNode.GetSingleIdentifier(MqlGeneratorTemplateType);
5142
var linqExpressionNode = mainTestMethodNode.GetSingleIdentifier(LinqMethodName).Parent.Parent;
5243

53-
return new SyntaxElements(root, classDeclarationSyntax, mainTestMethodNode, linqExpressionNode, queryableTypeNode);
44+
return new MqlGeneratorTestMethodTemplate(root, classDeclarationSyntax, mainTestMethodNode, linqExpressionNode, queryableTypeNode, AnalysisType.Linq);
5445
}
5546

5647
public (string newMethodName, MethodDeclarationSyntax newMethodDeclaration) GenerateMqlGeneratorMethod(string collectionTypeName, SyntaxNode linqExpression)
5748
{
58-
var newMethodDeclaration = _syntaxElements.TestMethodNode.ReplaceNodes(_syntaxElements.NodesToReplace, (n, _) =>
49+
var newMethodDeclaration = _testMethodTemplate.TestMethodNode.ReplaceNodes(_testMethodTemplate.NodesToReplace, (n, _) =>
5950
n.Kind() switch
6051
{
61-
_ when n == _syntaxElements.LinqExpressionNode => linqExpression,
62-
_ when n == _syntaxElements.QueryableTypeNode => SyntaxFactory.IdentifierName(collectionTypeName),
52+
_ when n == _testMethodTemplate.ExpressionNode => linqExpression,
53+
_ when n == _testMethodTemplate.TypeNode => SyntaxFactory.IdentifierName(collectionTypeName),
6354
_ => throw new Exception($"Unrecognized node {n}")
6455
});
6556

66-
var newMqlGeneratorMethodName = $"{_syntaxElements.TestMethodNode.Identifier.Value}_{_nextTestMethodIndex++}";
57+
var newMqlGeneratorMethodName = $"{_testMethodTemplate.TestMethodNode.Identifier.Value}_{_nextTestMethodIndex++}";
6758
newMethodDeclaration = newMethodDeclaration.WithIdentifier(SyntaxFactory.Identifier(newMqlGeneratorMethodName));
6859

6960
return (newMqlGeneratorMethodName, newMethodDeclaration);
7061
}
7162

7263
public SyntaxTree GenerateSyntaxTree() =>
73-
_syntaxElements.Root.ReplaceNode(_syntaxElements.ClassDeclarationSyntax, _mqlGeneratorDeclarationSyntaxNew).SyntaxTree;
64+
_testMethodTemplate.Root.ReplaceNode(_testMethodTemplate.ClassDeclarationSyntax, _mqlGeneratorDeclarationSyntaxNew).SyntaxTree;
7465
}

Diff for: src/MongoDB.Analyzer/Core/Poco/AnalysisCodeGenerator.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ namespace MongoDB.Analyzer.Core.Poco;
1919

2020
internal static class AnalysisCodeGenerator
2121
{
22-
private static readonly PocoJsonGeneratorTemplateBuilder.SyntaxElements s_jsonGeneratorSyntaxElements;
22+
private static readonly MqlGeneratorTestMethodTemplate s_testMethodTemplate;
2323
private static readonly ParseOptions s_parseOptions;
2424

2525
static AnalysisCodeGenerator()
2626
{
2727
var jsonGeneratorSyntaxTree = GetCodeResource(ResourceNames.Poco.JsonGenerator);
28-
s_jsonGeneratorSyntaxElements = PocoJsonGeneratorTemplateBuilder.CreateSyntaxElements(jsonGeneratorSyntaxTree);
28+
s_testMethodTemplate = PocoJsonGeneratorTemplateBuilder.CreateTestMethodTemplate(jsonGeneratorSyntaxTree);
2929
s_parseOptions = jsonGeneratorSyntaxTree.Options;
3030
}
3131

@@ -59,7 +59,7 @@ public static CompilationResult Compile(MongoAnalysisContext context, Expression
5959

6060
public static SyntaxTree GenerateJsonGeneratorSyntaxTree(ExpressionsAnalysis pocoExpressionAnalysis)
6161
{
62-
var testCodeBuilder = new PocoJsonGeneratorTemplateBuilder(s_jsonGeneratorSyntaxElements);
62+
var testCodeBuilder = new PocoJsonGeneratorTemplateBuilder(s_testMethodTemplate);
6363
var generatedJsonMethodDeclarations = new List<MethodDeclarationSyntax>(pocoExpressionAnalysis.AnalysisNodeContexts.Length);
6464

6565
foreach (var pocoContext in pocoExpressionAnalysis.AnalysisNodeContexts)

Diff for: src/MongoDB.Analyzer/Core/Poco/PocoJsonGeneratorTemplateBuilder.cs

+10-18
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,27 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using MongoDB.Analyzer.Core.Utilities;
1516
using static MongoDB.Analyzer.Core.HelperResources.JsonSyntaxElements.Poco;
1617

1718
namespace MongoDB.Analyzer.Core.Poco;
1819

1920
internal sealed class PocoJsonGeneratorTemplateBuilder
2021
{
21-
internal record SyntaxElements(
22-
SyntaxNode Root,
23-
ClassDeclarationSyntax ClassDeclarationSyntax,
24-
MethodDeclarationSyntax TestMethodNode,
25-
PredefinedTypeSyntax PredefinedTypeNode)
26-
{
27-
public SyntaxNode[] NodesToReplace { get; } = new[] { PredefinedTypeNode };
28-
}
29-
30-
private readonly SyntaxElements _syntaxElements;
22+
private readonly MqlGeneratorTestMethodTemplate _testMethodTemplate;
3123
private ClassDeclarationSyntax _jsonGeneratorDeclarationSyntaxNew;
3224
private int _nextTestMethodIndex;
3325

34-
public PocoJsonGeneratorTemplateBuilder(SyntaxElements syntaxElements)
26+
public PocoJsonGeneratorTemplateBuilder(MqlGeneratorTestMethodTemplate syntaxElements)
3527
{
36-
_syntaxElements = syntaxElements;
37-
_jsonGeneratorDeclarationSyntaxNew = _syntaxElements.ClassDeclarationSyntax;
28+
_testMethodTemplate = syntaxElements;
29+
_jsonGeneratorDeclarationSyntaxNew = _testMethodTemplate.ClassDeclarationSyntax;
3830
}
3931

4032
public void AddJsonGeneratorMethods(MemberDeclarationSyntax[] methodDeclarations) =>
4133
_jsonGeneratorDeclarationSyntaxNew = _jsonGeneratorDeclarationSyntaxNew.AddMembers(methodDeclarations);
4234

43-
public static SyntaxElements CreateSyntaxElements(SyntaxTree jsonGeneratorSyntaxTree)
35+
public static MqlGeneratorTestMethodTemplate CreateTestMethodTemplate(SyntaxTree jsonGeneratorSyntaxTree)
4436
{
4537
var root = jsonGeneratorSyntaxTree.GetRoot();
4638
var classDeclarationSyntax = root.GetSingleClassDeclaration(JsonGenerator);
@@ -49,17 +41,17 @@ public static SyntaxElements CreateSyntaxElements(SyntaxTree jsonGeneratorSyntax
4941
var localDeclaration = mainTestMethodNode.DescendantNodes().OfType<LocalDeclarationStatementSyntax>().FirstOrDefault();
5042
var predefinedType = localDeclaration.DescendantNodes().OfType<PredefinedTypeSyntax>().FirstOrDefault();
5143

52-
return new(root, classDeclarationSyntax, mainTestMethodNode, predefinedType);
44+
return new(root, classDeclarationSyntax, mainTestMethodNode, null, predefinedType, AnalysisType.Poco);
5345
}
5446

5547
public (string newMethodName, MethodDeclarationSyntax newMethodDeclaration) GenerateJsonGeneratorMethod(ClassDeclarationSyntax poco)
5648
{
57-
var newMethodDeclaration = _syntaxElements.TestMethodNode.ReplaceNode(_syntaxElements.PredefinedTypeNode, SyntaxFactory.IdentifierName(poco.Identifier.ValueText));
58-
var newJsonGeneratorMethodName = $"{_syntaxElements.TestMethodNode.Identifier.Value}_{_nextTestMethodIndex++}";
49+
var newMethodDeclaration = _testMethodTemplate.TestMethodNode.ReplaceNode(_testMethodTemplate.TypeNode, SyntaxFactory.IdentifierName(poco.Identifier.ValueText));
50+
var newJsonGeneratorMethodName = $"{_testMethodTemplate.TestMethodNode.Identifier.Value}_{_nextTestMethodIndex++}";
5951
newMethodDeclaration = newMethodDeclaration.WithIdentifier(SyntaxFactory.Identifier(newJsonGeneratorMethodName));
6052
return (newJsonGeneratorMethodName, newMethodDeclaration);
6153
}
6254

6355
public SyntaxTree GenerateSyntaxTree() =>
64-
_syntaxElements.Root.ReplaceNode(_syntaxElements.ClassDeclarationSyntax, _jsonGeneratorDeclarationSyntaxNew).SyntaxTree;
56+
_testMethodTemplate.Root.ReplaceNode(_testMethodTemplate.ClassDeclarationSyntax, _jsonGeneratorDeclarationSyntaxNew).SyntaxTree;
6557
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2021-present MongoDB Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License")
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
namespace MongoDB.Analyzer.Core.Utilities;
16+
17+
internal sealed record MqlGeneratorTestMethodTemplate(
18+
SyntaxNode Root,
19+
ClassDeclarationSyntax ClassDeclarationSyntax,
20+
MethodDeclarationSyntax TestMethodNode,
21+
SyntaxNode ExpressionNode,
22+
SyntaxNode TypeNode,
23+
AnalysisType AnalysisType)
24+
{
25+
public SyntaxNode[] NodesToReplace => AnalysisType switch
26+
{
27+
AnalysisType.Poco => new[] { TypeNode },
28+
_ => new[] { ExpressionNode, TypeNode },
29+
};
30+
}

0 commit comments

Comments
 (0)