Skip to content

Commit 9339d6a

Browse files
committed
feat: Add tests for AggregatePropertySuffixAnalyzer and update diagnostic IDs
1 parent 07baa31 commit 9339d6a

File tree

4 files changed

+269
-11
lines changed

4 files changed

+269
-11
lines changed
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.Testing;
3+
using Xunit;
4+
using VerifyCS = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier<Weaviate.Client.Analyzers.AggregatePropertySuffixAnalyzer>;
5+
6+
namespace Weaviate.Client.Analyzers.Tests;
7+
8+
public class AggregatePropertySuffixAnalyzerTests
9+
{
10+
private const string TestStubCode =
11+
@"
12+
using System;
13+
using System.Collections.Generic;
14+
15+
namespace Weaviate.Client.Models
16+
{
17+
public class AggregateResult { }
18+
}
19+
20+
namespace Weaviate.Client.Models.Typed
21+
{
22+
using Weaviate.Client.Models;
23+
24+
public static class TypedResultConverter
25+
{
26+
public static AggregateResult<T> ToTyped<T>(this AggregateResult result) where T : new()
27+
{
28+
return new AggregateResult<T>();
29+
}
30+
}
31+
32+
public static class MetricsExtractor
33+
{
34+
public static string[] FromType<T>() => Array.Empty<string>();
35+
}
36+
37+
public class AggregateResult<T> where T : new()
38+
{
39+
public T Properties { get; set; } = new T();
40+
}
41+
}
42+
43+
namespace Weaviate.Client.Models.Aggregate
44+
{
45+
public class Text { }
46+
public class Integer { }
47+
public class Number { }
48+
public class Boolean { }
49+
public class Date { }
50+
}
51+
52+
namespace Weaviate.Client.Models.Typed
53+
{
54+
[AttributeUsage(AttributeTargets.Property)]
55+
public class TextMetricsAttribute : Attribute { }
56+
57+
[AttributeUsage(AttributeTargets.Property)]
58+
public class IntegerMetricsAttribute : Attribute { }
59+
60+
[AttributeUsage(AttributeTargets.Property)]
61+
public class NumberMetricsAttribute : Attribute { }
62+
63+
[AttributeUsage(AttributeTargets.Property)]
64+
public class BooleanMetricsAttribute : Attribute { }
65+
66+
[AttributeUsage(AttributeTargets.Property)]
67+
public class DateMetricsAttribute : Attribute { }
68+
69+
[AttributeUsage(AttributeTargets.Property)]
70+
public class MetricsForPropertyAttribute : Attribute
71+
{
72+
public MetricsForPropertyAttribute(string propertyName) { }
73+
}
74+
}
75+
";
76+
77+
#region WEAVIATE005 - Missing Suffix Tests
78+
79+
[Fact]
80+
public async Task MissingSuffix_OnToTypedCall_ReportsDiagnostic()
81+
{
82+
var testCode =
83+
TestStubCode
84+
+ @"
85+
namespace Test
86+
{
87+
using Weaviate.Client.Models;
88+
using Weaviate.Client.Models.Typed;
89+
90+
public class MyModel
91+
{
92+
public int Age { get; set; }
93+
}
94+
95+
public class TestClass
96+
{
97+
public void TestMethod()
98+
{
99+
var result = new AggregateResult();
100+
var typed = result.ToTyped<MyModel>();
101+
}
102+
}
103+
}";
104+
105+
var expected = VerifyCS
106+
.Diagnostic(AggregatePropertySuffixAnalyzer.MissingSuffixDiagnosticId)
107+
.WithArguments("Age", "MyModel")
108+
.WithSpan("/0/Test0.cs", 81, 40, 81, 47);
109+
110+
await VerifyCS.VerifyAnalyzerAsync(testCode, expected);
111+
}
112+
113+
[Fact]
114+
public async Task ValidSuffixAsCount_NoDiagnostic()
115+
{
116+
var testCode =
117+
TestStubCode
118+
+ @"
119+
namespace Test
120+
{
121+
using Weaviate.Client.Models;
122+
using Weaviate.Client.Models.Typed;
123+
124+
public class MyModel
125+
{
126+
public long? AgeAsCount { get; set; }
127+
}
128+
129+
public class TestClass
130+
{
131+
public void TestMethod()
132+
{
133+
var result = new AggregateResult();
134+
var typed = result.ToTyped<MyModel>();
135+
}
136+
}
137+
}";
138+
139+
await VerifyCS.VerifyAnalyzerAsync(testCode);
140+
}
141+
142+
#endregion
143+
144+
#region WEAVIATE006 - Invalid Suffix Type Tests
145+
146+
[Fact]
147+
public async Task InvalidSuffixType_CountOnString_ReportsDiagnostic()
148+
{
149+
var testCode =
150+
TestStubCode
151+
+ @"
152+
namespace Test
153+
{
154+
using Weaviate.Client.Models;
155+
using Weaviate.Client.Models.Typed;
156+
157+
public class MyModel
158+
{
159+
public string NameAsCount { get; set; }
160+
}
161+
162+
public class TestClass
163+
{
164+
public void TestMethod()
165+
{
166+
var result = new AggregateResult();
167+
var typed = result.ToTyped<MyModel>();
168+
}
169+
}
170+
}";
171+
172+
var expected = VerifyCS
173+
.Diagnostic(AggregatePropertySuffixAnalyzer.InvalidSuffixTypeDiagnosticId)
174+
.WithArguments("NameAsCount", "MyModel", "Count", "long or int or double", "string")
175+
.WithSpan("/0/Test0.cs", 81, 40, 81, 47);
176+
177+
await VerifyCS.VerifyAnalyzerAsync(testCode, expected);
178+
}
179+
180+
#endregion
181+
182+
#region WEAVIATE004 - Wrong Attribute Type Tests
183+
184+
[Fact]
185+
public async Task WrongAttributeType_NumberMetricsOnText_ReportsDiagnostic()
186+
{
187+
var testCode =
188+
TestStubCode
189+
+ @"
190+
namespace Test
191+
{
192+
using Weaviate.Client.Models;
193+
using Weaviate.Client.Models.Typed;
194+
using Weaviate.Client.Models.Aggregate;
195+
196+
public class MyModel
197+
{
198+
[NumberMetrics]
199+
public Text Name { get; set; }
200+
}
201+
202+
public class TestClass
203+
{
204+
public void TestMethod()
205+
{
206+
var result = new AggregateResult();
207+
var typed = result.ToTyped<MyModel>();
208+
}
209+
}
210+
}";
211+
212+
var expected = VerifyCS
213+
.Diagnostic(AggregatePropertySuffixAnalyzer.WrongAttributeTypeDiagnosticId)
214+
.WithArguments("Name", "Text", "Number")
215+
.WithSpan("/0/Test0.cs", 83, 40, 83, 47);
216+
217+
await VerifyCS.VerifyAnalyzerAsync(testCode, expected);
218+
}
219+
220+
[Fact]
221+
public async Task ValidAttributeType_NumberMetricsOnNumber_NoDiagnostic()
222+
{
223+
var testCode =
224+
TestStubCode
225+
+ @"
226+
namespace Test
227+
{
228+
using Weaviate.Client.Models;
229+
using Weaviate.Client.Models.Typed;
230+
using Weaviate.Client.Models.Aggregate;
231+
232+
public class MyModel
233+
{
234+
[NumberMetrics]
235+
public Number Price { get; set; }
236+
}
237+
238+
public class TestClass
239+
{
240+
public void TestMethod()
241+
{
242+
var result = new AggregateResult();
243+
var typed = result.ToTyped<MyModel>();
244+
}
245+
}
246+
}";
247+
248+
await VerifyCS.VerifyAnalyzerAsync(testCode);
249+
}
250+
251+
#endregion
252+
}

src/Weaviate.Client.Analyzers/AggregatePropertySuffixAnalyzer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ namespace Weaviate.Client.Analyzers;
1616
[DiagnosticAnalyzer(LanguageNames.CSharp)]
1717
public class AggregatePropertySuffixAnalyzer : DiagnosticAnalyzer
1818
{
19-
public const string MissingSuffixDiagnosticId = "WEAVIATE002";
20-
public const string InvalidSuffixTypeDiagnosticId = "WEAVIATE003";
19+
public const string MissingSuffixDiagnosticId = "WEAVIATE005";
20+
public const string InvalidSuffixTypeDiagnosticId = "WEAVIATE006";
2121
public const string WrongAttributeTypeDiagnosticId = "WEAVIATE004";
2222
private const string Category = "Usage";
2323

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11

22
### New Rules
33

4-
Rule ID | Category | Severity | Notes
5-
--------|----------|----------|-------
6-
WEAVIATE002 | Usage | Warning | Aggregate property missing suffix. Triggers when ToTyped<T>() or MetricsExtractor.FromType<T>() is called with the type.
7-
WEAVIATE003 | Usage | Warning | Invalid type for aggregate suffix. Triggers when ToTyped<T>() or MetricsExtractor.FromType<T>() is called with the type.
8-
WEAVIATE004 | Usage | Warning | Wrong metrics attribute for aggregate type. Triggers when using mismatched attribute (e.g., NumberMetrics on Aggregate.Text).
4+
Rule ID | Category | Severity | Notes
5+
------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------
6+
WEAVIATE002 | Usage | Error | VectorizerFactoryAnalyzer: Missing property in VectorizerFactory call
7+
WEAVIATE003 | Usage | Error | VectorizerFactoryAnalyzer: Missing weight field in multi-vector configuration
8+
WEAVIATE004 | Usage | Warning | AggregatePropertySuffixAnalyzer: Wrong metrics attribute for aggregate type. Triggers when using mismatched attribute (e.g., NumberMetrics on Aggregate.Text).
9+
WEAVIATE005 | Usage | Warning | AggregatePropertySuffixAnalyzer: Aggregate property missing suffix. Triggers when ToTyped<T>() or MetricsExtractor.FromType<T>() is called with the type.
10+
WEAVIATE006 | Usage | Warning | AggregatePropertySuffixAnalyzer: Invalid type for aggregate suffix. Triggers when ToTyped<T>() or MetricsExtractor.FromType<T>() is called with the type.

src/Weaviate.Client.Tests/Unit/TestTypedAggregateResults.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,15 +577,19 @@ public void GroupByToTyped_MapsFullTypesPerGroup()
577577

578578
// First group (Tech)
579579
Assert.NotNull(typed.Groups[0].Properties.Title);
580-
Assert.Equal(60, typed.Groups[0].Properties.Title.Count);
580+
Assert.NotNull(typed.Groups[0].Properties.Title!.Count);
581+
Assert.Equal(60, typed.Groups[0].Properties.Title!.Count!);
581582
Assert.NotNull(typed.Groups[0].Properties.WordCount);
582-
Assert.Equal(2000.0, typed.Groups[0].Properties.WordCount.Mean);
583+
Assert.NotNull(typed.Groups[0].Properties.WordCount!.Mean);
584+
Assert.Equal(2000.0, typed.Groups[0].Properties.WordCount!.Mean!.Value);
583585

584586
// Second group (Science)
585587
Assert.NotNull(typed.Groups[1].Properties.Title);
586-
Assert.Equal(40, typed.Groups[1].Properties.Title.Count);
588+
Assert.NotNull(typed.Groups[1].Properties.Title!.Count);
589+
Assert.Equal(40, typed.Groups[1].Properties.Title!.Count!);
587590
Assert.NotNull(typed.Groups[1].Properties.WordCount);
588-
Assert.Equal(3000.0, typed.Groups[1].Properties.WordCount.Mean);
591+
Assert.NotNull(typed.Groups[1].Properties.WordCount!.Mean);
592+
Assert.Equal(3000.0, typed.Groups[1].Properties.WordCount!.Mean!.Value);
589593
}
590594

591595
[Fact]

0 commit comments

Comments
 (0)