Skip to content

Commit f42af31

Browse files
VS-97: Handle Enum Remapping in LINQ For Type Arguments (#39)
Co-authored-by: BorisDog <[email protected]>
1 parent 62c2281 commit f42af31

File tree

3 files changed

+74
-41
lines changed

3 files changed

+74
-41
lines changed

src/MongoDB.Analyzer/Core/Linq/LinqExpressionProcessor.cs

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,10 @@ private static (SyntaxNode RewrittenLinqExpression, ConstantsMapper ConstantsMap
227227
.DescendantNodes(n => n != deepestMongoQueryableNode)
228228
.OfType<IdentifierNameSyntax>()
229229
.Where(identifierNode =>
230-
{
231-
var symbolInfo = semanticModel.GetSymbolInfo(identifierNode);
232-
return symbolInfo.Symbol != null && IsChildOfLambdaOrQueryParameter(rewriteContext, identifierNode, symbolInfo);
233-
})
230+
{
231+
var symbolInfo = semanticModel.GetSymbolInfo(identifierNode);
232+
return symbolInfo.Symbol != null && IsChildOfLambdaOrQueryParameter(rewriteContext, identifierNode, symbolInfo);
233+
})
234234
.ToArray();
235235

236236
foreach (var identifierNode in linqExpressionNode.DescendantNodes(n => n != deepestMongoQueryableNode).OfType<IdentifierNameSyntax>())
@@ -291,43 +291,10 @@ private static RewriteResult HandleRemappedType(
291291
SimpleNameSyntax identifierNode)
292292
{
293293
var typeInfo = rewriteContext.SemanticModel.GetTypeInfo(identifierNode);
294-
var remmapedType = rewriteContext.TypesProcessor.GetTypeSymbolToGeneratedTypeMapping(typeInfo.Type);
295-
296-
if (remmapedType == null)
297-
{
298-
return RewriteResult.Invalid;
299-
}
300-
301-
SyntaxNode nodeToReplace = identifierNode;
302-
var identifierName = identifierNode.Identifier.Text;
303-
304-
if (typeInfo.Type.TypeKind == TypeKind.Enum)
305-
{
306-
if (nodeToReplace.Parent is MemberAccessExpressionSyntax memberAccessExpressionSyntax)
307-
{
308-
nodeToReplace = memberAccessExpressionSyntax;
309-
identifierName = memberAccessExpressionSyntax.Name.Identifier.Text;
310-
}
311-
else
312-
{
313-
return RewriteResult.Ignore;
314-
}
315-
}
316-
else
317-
{
318-
while (nodeToReplace.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression))
319-
{
320-
nodeToReplace = nodeToReplace.Parent;
321-
}
322-
}
323-
324-
SyntaxNode newNode = identifierNode.Parent.Kind() switch
325-
{
326-
SyntaxKind.SimpleMemberAccessExpression => SyntaxFactoryUtilities.SimpleMemberAccess(remmapedType, identifierName),
327-
_ => SyntaxFactory.IdentifierName(remmapedType)
328-
};
294+
var remappedType = rewriteContext.TypesProcessor.GetTypeSymbolToGeneratedTypeMapping(typeInfo.Type);
295+
var result = remappedType != null ? new(identifierNode, SyntaxFactory.IdentifierName(remappedType)) : RewriteResult.Invalid;
329296

330-
return new RewriteResult(nodeToReplace, newNode);
297+
return result;
331298
}
332299

333300
private static RewriteResult HandleField(

tests/MongoDB.Analyzer.Tests.Common.TestCases/Linq/LinqConstantsReplacement.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,6 @@ public void Query_syntax()
417417
private Person _fieldPerson = new() { Name = "fieldPersonName" };
418418
private Person PropertyPerson { get; } = new Person() { Name = "propertyPersonName" };
419419

420-
421420
private Person GetPerson() => new();
422421
private Person GetPerson(long ticksSinceBirth) => new() { TicksSinceBirth = ticksSinceBirth };
423422

tests/MongoDB.Analyzer.Tests.Common.TestCases/Linq/LinqEnums.cs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System;
1516
using System.Linq;
1617
using MongoDB.Analyzer.Tests.Common.DataModel;
18+
using MongoDB.Driver;
1719
using MongoDB.Driver.Linq;
1820

1921
namespace MongoDB.Analyzer.Tests.Common.TestCases.Linq
@@ -101,5 +103,70 @@ public void Query_Syntax()
101103
where person.Vehicle.VehicleType.Type == VehicleTypeEnum.Bus || person.Vehicle.VehicleType.Type == VehicleTypeEnum.Motorcylce
102104
select person.Vehicle.LicenceNumber;
103105
}
106+
107+
108+
[MQL("aggregate([{ \"$match\" : { \"MPG\" : { \"$gt\" : 20.0 } } }, { \"$project\" : { \"Item1\" : \"$VehicleMake\", \"Item2\" : \"$Type\", \"_id\" : 0 } }])")]
109+
public void Enum_in_type_argument_1()
110+
{
111+
_ = GetMongoCollection<VehicleType>().AsQueryable()
112+
.Where(v => v.MPG > 20)
113+
.Select(v => new Tuple<VehicleMake, VehicleTypeEnum>(v.VehicleMake, v.Type));
114+
}
115+
116+
[MQL("aggregate([{ \"$match\" : { \"MPG\" : { \"$gt\" : 20.0 } } }, { \"$project\" : { \"Item1\" : \"$VehicleMake\", \"Item2\" : \"$Type\", \"_id\" : 0 } }])")]
117+
public void Enum_in_type_argument_query_syntax_1()
118+
{
119+
_ = from vehicleType in GetMongoQueryable<VehicleType>()
120+
where vehicleType.MPG > 20
121+
select new Tuple<VehicleMake, VehicleTypeEnum>(vehicleType.VehicleMake, vehicleType.Type);
122+
}
123+
124+
[MQL("aggregate([{ \"$match\" : { \"MPG\" : { \"$gt\" : 20.0 } } }, { \"$project\" : { \"__fld0\" : [0, 1, 2], \"_id\" : 0 } }])")]
125+
public void Enum_in_type_argument_2()
126+
{
127+
_ = GetMongoCollection<VehicleType>().AsQueryable()
128+
.Where(v => v.MPG > 20)
129+
.Select(v => new System.Collections.Generic.List<VehicleTypeEnum> { VehicleTypeEnum.Bus, VehicleTypeEnum.Car, VehicleTypeEnum.Motorcylce });
130+
}
131+
132+
[MQL("aggregate([{ \"$match\" : { \"MPG\" : { \"$gt\" : 20.0 } } }, { \"$project\" : { \"__fld0\" : [0, 1, 2], \"_id\" : 0 } }])")]
133+
public void Enum_in_type_argument_query_syntax_2()
134+
{
135+
_ = from vehicleType in GetMongoQueryable<VehicleType>()
136+
where vehicleType.MPG > 20
137+
select new System.Collections.Generic.List<VehicleTypeEnum> { VehicleTypeEnum.Bus, VehicleTypeEnum.Car, VehicleTypeEnum.Motorcylce };
138+
}
139+
140+
[MQL("aggregate([{ \"$match\" : { \"SiblingsCount\" : { \"$gt\" : 10 } } }, { \"$project\" : { \"__fld0\" : { \"Bus\" : 0, \"Car\" : 1 }, \"_id\" : 0 } }])")]
141+
public void Enum_in_type_argument_3()
142+
{
143+
_ = GetMongoCollection<Person>().AsQueryable()
144+
.Where(p => p.SiblingsCount > 10)
145+
.Select(p => new System.Collections.Generic.Dictionary<string, VehicleTypeEnum> { { "Bus", VehicleTypeEnum.Bus }, { "Car", VehicleTypeEnum.Car } });
146+
}
147+
148+
[MQL("aggregate([{ \"$match\" : { \"SiblingsCount\" : { \"$gt\" : 10 } } }, { \"$project\" : { \"__fld0\" : { \"Bus\" : 0, \"Car\" : 1 }, \"_id\" : 0 } }])")]
149+
public void Enum_in_type_argument_query_syntax_3()
150+
{
151+
_ = from person in GetMongoQueryable<Person>()
152+
where person.SiblingsCount > 10
153+
select new System.Collections.Generic.Dictionary<string, VehicleTypeEnum> { { "Bus", VehicleTypeEnum.Bus }, { "Car", VehicleTypeEnum.Car } };
154+
}
155+
156+
[MQL("aggregate([{ \"$match\" : { \"MPG\" : { \"$gt\" : 20.0 } } }, { \"$project\" : { \"Item1\" : \"$VehicleMake\", \"Item2\" : { \"Item1\" : \"$Type\", \"Item2\" : \"$Type\" }, \"_id\" : 0 } }])")]
157+
public void Enum_in_nested_type_argument()
158+
{
159+
_ = GetMongoCollection<VehicleType>().AsQueryable()
160+
.Where(v => v.MPG > 20)
161+
.Select(v => new Tuple<VehicleMake, Tuple<VehicleTypeEnum, VehicleTypeEnum>>(v.VehicleMake, new Tuple<VehicleTypeEnum, VehicleTypeEnum>(v.Type, v.Type)));
162+
}
163+
164+
[MQL("aggregate([{ \"$match\" : { \"MPG\" : { \"$gt\" : 20.0 } } }, { \"$project\" : { \"Item1\" : \"$VehicleMake\", \"Item2\" : { \"Item1\" : \"$Type\", \"Item2\" : \"$Type\" }, \"_id\" : 0 } }])")]
165+
public void Enum_in_nested_type_argument_query_syntax()
166+
{
167+
_ = from vehicleType in GetMongoQueryable<VehicleType>()
168+
where vehicleType.MPG > 20
169+
select new Tuple<VehicleMake, Tuple<VehicleTypeEnum, VehicleTypeEnum>>(vehicleType.VehicleMake, new Tuple<VehicleTypeEnum, VehicleTypeEnum>(vehicleType.Type, vehicleType.Type));
170+
}
104171
}
105172
}

0 commit comments

Comments
 (0)