Skip to content

Commit 3d3c79d

Browse files
committed
.
1 parent 572b8be commit 3d3c79d

5 files changed

Lines changed: 45 additions & 51 deletions

File tree

src/GraphQL.EntityFramework.Analyzers.Tests/FieldBuilderResolveAnalyzerTests.cs

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
using GraphQL.EntityFramework.Analyzers;
2-
using GraphQL.Types;
3-
using Microsoft.CodeAnalysis;
4-
using Microsoft.CodeAnalysis.CSharp;
5-
using Microsoft.CodeAnalysis.Diagnostics;
6-
using Microsoft.EntityFrameworkCore;
7-
8-
namespace GraphQL.EntityFramework.Tests;
1+
using GraphQL.EntityFramework;
92

103
public class FieldBuilderResolveAnalyzerTests
114
{
@@ -205,7 +198,7 @@ public ChildGraphType(IEfGraphQLService<TestDbContext> graphQlService) : base(gr
205198
var diagnostics = await GetDiagnosticsAsync(source);
206199
// Should warn because Name, Age, IsActive, CreatedDate are scalar properties, not PK/FK
207200
Assert.Equal(2, diagnostics.Length); // Two Resolve calls
208-
Assert.All(diagnostics, d => Assert.Equal("GQLEF002", d.Id));
201+
Assert.All(diagnostics, _ => Assert.Equal("GQLEF002", _.Id));
209202
}
210203

211204
[Fact]
@@ -388,13 +381,18 @@ static async Task<Diagnostic[]> GetDiagnosticsAsync(string source)
388381

389382
// Add specific assemblies we need, avoiding conflicts
390383
var requiredAssemblies = new[]
391-
{
392-
typeof(object).Assembly, // System.Private.CoreLib
393-
typeof(Console).Assembly, // System.Console
394-
typeof(IEfGraphQLService<>).Assembly, // GraphQL.EntityFramework
395-
typeof(DbContext).Assembly, // EF Core
396-
typeof(ObjectGraphType).Assembly, // GraphQL
397-
typeof(IQueryable<>).Assembly, // System.Linq.Expressions
384+
{ // System.Private.CoreLib
385+
typeof(object).Assembly,
386+
// System.Console
387+
typeof(Console).Assembly,
388+
// GraphQL.EntityFramework
389+
typeof(IEfGraphQLService<>).Assembly,
390+
// EF Core
391+
typeof(DbContext).Assembly,
392+
// GraphQL
393+
typeof(ObjectGraphType).Assembly,
394+
// System.Linq.Expressions
395+
typeof(IQueryable<>).Assembly,
398396
};
399397

400398
foreach (var assembly in requiredAssemblies)
@@ -410,20 +408,23 @@ static async Task<Diagnostic[]> GetDiagnosticsAsync(string source)
410408
{
411409
if (!assembly.IsDynamic &&
412410
!string.IsNullOrEmpty(assembly.Location) &&
413-
!references.Any(r => r.Display == assembly.Location))
411+
references.All(_ => _.Display != assembly.Location))
414412
{
415413
var name = assembly.GetName().Name ?? "";
416-
if ((name.StartsWith("System.") || name.StartsWith("Microsoft.")) &&
417-
!name.Contains("xunit", StringComparison.OrdinalIgnoreCase))
414+
if ((!name.StartsWith("System.") &&
415+
!name.StartsWith("Microsoft.")) ||
416+
name.Contains("xunit", StringComparison.OrdinalIgnoreCase))
417+
{
418+
continue;
419+
}
420+
421+
try
422+
{
423+
references.Add(MetadataReference.CreateFromFile(assembly.Location));
424+
}
425+
catch
418426
{
419-
try
420-
{
421-
references.Add(MetadataReference.CreateFromFile(assembly.Location));
422-
}
423-
catch
424-
{
425-
// Ignore assemblies that can't be referenced
426-
}
427+
// Ignore assemblies that can't be referenced
427428
}
428429
}
429430
}
@@ -442,16 +443,16 @@ static async Task<Diagnostic[]> GetDiagnosticsAsync(string source)
442443
var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync();
443444

444445
// Check for compilation errors
445-
var compilationErrors = allDiagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).ToArray();
446+
var compilationErrors = allDiagnostics.Where(_ => _.Severity == DiagnosticSeverity.Error).ToArray();
446447
if (compilationErrors.Length > 0)
447448
{
448-
var errorMessages = string.Join("\n", compilationErrors.Select(e => $"{e.Id}: {e.GetMessage()}"));
449+
var errorMessages = string.Join("\n", compilationErrors.Select(_ => $"{_.Id}: {_.GetMessage()}"));
449450
throw new($"Compilation errors:\n{errorMessages}");
450451
}
451452

452453
// Filter to only GQLEF002 diagnostics
453454
return allDiagnostics
454-
.Where(d => d.Id == "GQLEF002")
455+
.Where(_ => _.Id == "GQLEF002")
455456
.ToArray();
456457
}
457458
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1+
global using GraphQL.EntityFramework.Analyzers;
2+
global using GraphQL.Types;
3+
global using Microsoft.CodeAnalysis;
4+
global using Microsoft.CodeAnalysis.CSharp;
5+
global using Microsoft.CodeAnalysis.Diagnostics;
6+
global using Microsoft.EntityFrameworkCore;
17
global using Xunit;

src/GraphQL.EntityFramework.Analyzers/FieldBuilderResolveAnalyzer.cs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ static bool AccessesNavigationProperties(LambdaExpressionSyntax lambda, Semantic
155155

156156
// Find all member access expressions in the lambda
157157
var memberAccesses = body.DescendantNodesAndSelf()
158-
.OfType<MemberAccessExpressionSyntax>()
159-
.ToList();
158+
.OfType<MemberAccessExpressionSyntax>();
160159

161160
foreach (var memberAccess in memberAccesses)
162161
{
@@ -252,26 +251,14 @@ memberAccess is
252251
return false;
253252
}
254253

255-
static bool IsSafeProperty(IPropertySymbol propertySymbol)
256-
{
254+
static bool IsSafeProperty(IPropertySymbol propertySymbol) =>
257255
// Only primary keys and foreign keys are safe to access
258256
// because they are always included in EF projections
259-
260257
// Check if it's a primary key (Id, EntityId, etc.)
261-
if (IsPrimaryKeyProperty(propertySymbol))
262-
{
263-
return true;
264-
}
265-
258+
IsPrimaryKeyProperty(propertySymbol) ||
266259
// Check if it's a foreign key (ParentId, UserId, etc.)
267-
if (IsForeignKeyProperty(propertySymbol))
268-
{
269-
return true;
270-
}
271-
272260
// Everything else (navigation properties, scalar properties) is unsafe
273-
return false;
274-
}
261+
IsForeignKeyProperty(propertySymbol);
275262

276263
static bool IsPrimaryKeyProperty(IPropertySymbol propertySymbol)
277264
{

src/GraphQL.EntityFramework.slnx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
<Project Path="Benchmarks/Benchmarks.csproj" />
1212
<Project Path="GraphQL.EntityFramework.Analyzers.Tests/GraphQL.EntityFramework.Analyzers.Tests.csproj" />
1313
<Project Path="GraphQL.EntityFramework.Analyzers/GraphQL.EntityFramework.Analyzers.csproj" />
14-
<Project Path="GraphQL.EntityFramework/GraphQL.EntityFramework.csproj" />
14+
<Project Path="GraphQL.EntityFramework/GraphQL.EntityFramework.csproj" >
15+
<BuildDependency Project="GraphQL.EntityFramework.Analyzers/GraphQL.EntityFramework.Analyzers.csproj" />
16+
</Project>
1517
<Project Path="SampleWeb.Tests/SampleWeb.Tests.csproj" />
1618
<Project Path="SampleWeb/SampleWeb.csproj" />
1719
<Project Path="Snippets/Snippets.csproj" />

src/GraphQL.EntityFramework/GraphQL.EntityFramework.csproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@
3030
<Using Include="GraphQL.Execution" />
3131
<Using Include="GraphQL.Builders" />
3232
<Using Include="System.Text.RegularExpressions" />
33-
</ItemGroup>
34-
<ItemGroup>
35-
<ProjectReference Include="..\GraphQL.EntityFramework.Analyzers\GraphQL.EntityFramework.Analyzers.csproj">
33+
<ProjectReference Condition="$(Configuration)=='Release'" Include="..\GraphQL.EntityFramework.Analyzers\GraphQL.EntityFramework.Analyzers.csproj">
3634
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
3735
<OutputItemType>Analyzer</OutputItemType>
3836
</ProjectReference>

0 commit comments

Comments
 (0)