Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,30 @@ public class VectorizerFactory
{
Model = model
// Missing: BaseURL = baseURL
// Also missing: ImageFields, TextFields, VideoFields (no params)
};
}
}";

var expected = VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "BaseURL");
var expected = new[]
{
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "BaseURL"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "ImageFields"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "TextFields"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "VideoFields"),
};

await VerifyCS.VerifyAnalyzerAsync(testCode, expected);
}
Expand All @@ -90,12 +106,18 @@ public class VectorizerFactory
{
public VectorizerConfig TestVectorizer(
string? model = null,
string? baseURL = null
string? baseURL = null,
WeightedFields? imageFields = null,
WeightedFields? textFields = null,
WeightedFields? videoFields = null
) =>
new Models.Vectorizer.TestVectorizer
{
Model = model,
BaseURL = baseURL
BaseURL = baseURL,
ImageFields = imageFields,
TextFields = textFields,
VideoFields = videoFields
};
}
}";
Expand All @@ -116,7 +138,7 @@ namespace Weaviate.Client

public class VectorizerFactory
{
public VectorizerConfig TestVectorizer(
public VectorizerConfig {|#0:TestVectorizer|}(
WeightedFields imageFields,
WeightedFields textFields,
WeightedFields videoFields
Expand All @@ -126,15 +148,26 @@ WeightedFields videoFields
ImageFields = imageFields,
TextFields = textFields,
VideoFields = videoFields,
{|#0:Weights = VectorizerWeights.FromWeightedFields(imageFields, textFields)|}
{|#1:Weights = VectorizerWeights.FromWeightedFields(imageFields, textFields)|}
};
}
}";

var expected = VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingWeightFieldDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "videoFields");
var expected = new[]
{
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingWeightFieldDiagnosticId)
.WithLocation(1)
.WithArguments("TestVectorizer", "videoFields"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "Model"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "BaseURL"),
};

await VerifyCS.VerifyAnalyzerAsync(testCode, expected);
}
Expand All @@ -155,10 +188,14 @@ public class VectorizerFactory
public VectorizerConfig TestVectorizer(
WeightedFields imageFields,
WeightedFields textFields,
WeightedFields videoFields
WeightedFields videoFields,
string? model = null,
string? baseURL = null
) =>
new Models.Vectorizer.TestVectorizer
{
Model = model,
BaseURL = baseURL,
ImageFields = imageFields,
TextFields = textFields,
VideoFields = videoFields,
Expand Down Expand Up @@ -186,10 +223,14 @@ public class VectorizerFactory
public VectorizerConfig TestVectorizer(
WeightedFields imageFields,
WeightedFields textFields,
WeightedFields videoFields
WeightedFields videoFields,
string? model = null,
string? baseURL = null
) =>
new Models.Vectorizer.TestVectorizer
{
Model = model,
BaseURL = baseURL,
ImageFields = imageFields,
TextFields = textFields,
VideoFields = videoFields,
Expand All @@ -214,11 +255,19 @@ namespace Weaviate.Client
public class VectorizerFactory
{
public VectorizerConfig TestVectorizer(
string? model = null
string? model = null,
string? baseURL = null,
WeightedFields? imageFields = null,
WeightedFields? textFields = null,
WeightedFields? videoFields = null
) =>
new Models.Vectorizer.TestVectorizer
{
Model = model
Model = model,
BaseURL = baseURL,
ImageFields = imageFields,
TextFields = textFields,
VideoFields = videoFields
};
}
}";
Expand Down Expand Up @@ -246,14 +295,30 @@ public class VectorizerFactoryMulti
{
Model = model
// Missing: BaseURL = baseURL
// Also missing: ImageFields, TextFields, VideoFields (no params)
};
}
}";

var expected = VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "BaseURL");
var expected = new[]
{
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "BaseURL"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "ImageFields"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "TextFields"),
VerifyCS
.Diagnostic(VectorizerFactoryAnalyzer.MissingPropertyDiagnosticId)
.WithLocation(0)
.WithArguments("TestVectorizer", "VideoFields"),
};

await VerifyCS.VerifyAnalyzerAsync(testCode, expected);
}
Expand Down
6 changes: 4 additions & 2 deletions src/Weaviate.Client.Analyzers/AnalyzerReleases.Shipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
### New Rules

Rule ID | Category | Severity | Notes
------------|----------|----------|-----------------------------------------------------
WEAVIATE001 | Usage | Error | AutoArray<T> should only be used as method parameter
------------|----------|----------|-----------------------------------------------------------------
WEAVIATE001 | Usage | Warning | AutoArrayUsageAnalyzer - AutoArray should only be used as method parameter
WEAVIATE002 | Usage | Error | VectorizerFactoryAnalyzer - Missing property initialization
WEAVIATE003 | Usage | Error | VectorizerFactoryAnalyzer - Missing field in Weights calculation
7 changes: 2 additions & 5 deletions src/Weaviate.Client.Analyzers/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
WEAVIATE001 | Usage | Error | AutoArrayUsageAnalyzer
WEAVIATE002 | Usage | Warning | VectorizerFactoryAnalyzer - Missing property initialization
WEAVIATE003 | Usage | Warning | VectorizerFactoryAnalyzer - Missing field in Weights calculation
Rule ID | Category | Severity | Notes
------------|----------|----------|-----------------------------------------------------------------
2 changes: 1 addition & 1 deletion src/Weaviate.Client.Analyzers/AutoArrayUsageAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class AutoArrayUsageAnalyzer : DiagnosticAnalyzer
Title,
MessageFormat,
Category,
DiagnosticSeverity.Error,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: Description
);
Expand Down
45 changes: 24 additions & 21 deletions src/Weaviate.Client.Analyzers/VectorizerFactoryAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ public class VectorizerFactoryAnalyzer : DiagnosticAnalyzer
private const string Category = "Usage";

private static readonly LocalizableString MissingPropertyTitle =
"Vectorizer factory method missing property initialization";
"Vectorizer factory method missing property initialization or parameter";
private static readonly LocalizableString MissingPropertyMessageFormat =
"Factory method creating '{0}' does not initialize property '{1}'";
"Factory method creating '{0}' does not have a way to set property '{1}'. Add a parameter for it or initialize it in the object initializer.";
private static readonly LocalizableString MissingPropertyDescription =
"All properties of a vectorizer config should be initializable through the factory method.";
"All public properties of a vectorizer config should be initializable through factory method parameters or explicitly initialized in the object initializer to ensure completeness.";

private static readonly LocalizableString MissingWeightFieldTitle =
"Vectorizer factory method missing field in Weights calculation";
Expand All @@ -34,7 +34,7 @@ public class VectorizerFactoryAnalyzer : DiagnosticAnalyzer
MissingPropertyTitle,
MissingPropertyMessageFormat,
Category,
DiagnosticSeverity.Warning,
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: MissingPropertyDescription
);
Expand All @@ -44,7 +44,7 @@ public class VectorizerFactoryAnalyzer : DiagnosticAnalyzer
MissingWeightFieldTitle,
MissingWeightFieldMessageFormat,
Category,
DiagnosticSeverity.Warning,
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: MissingWeightFieldDescription
);
Expand Down Expand Up @@ -169,24 +169,27 @@ SemanticModel semanticModel
// Check if there's a corresponding parameter for this property
var propertyNameLower = property.Name.ToLowerInvariant();

// Handle special mappings (e.g., BaseURL -> baseURL, VectorizeCollectionName -> vectorizeCollectionName)
// Convert PascalCase to camelCase for property name
var camelCasePropertyName =
property.Name.Length > 0
? char.ToLowerInvariant(property.Name[0]) + property.Name.Substring(1)
: property.Name;

var hasCorrespondingParameter =
parameterNames.Contains(propertyNameLower)
|| parameterNames.Contains(
property.Name.Substring(0, 1).ToLowerInvariant() + property.Name.Substring(1)
);

// Only warn if there's a parameter but it's not being used
if (hasCorrespondingParameter)
{
var diagnostic = Diagnostic.Create(
MissingPropertyRule,
methodDeclaration.Identifier.GetLocation(),
namedType.Name,
property.Name
);
context.ReportDiagnostic(diagnostic);
}
|| parameterNames.Contains(camelCasePropertyName.ToLowerInvariant());

// Warn if property is not initialized AND either:
// 1. There's a corresponding parameter (parameter exists but not used), OR
// 2. There's NO parameter and property isn't initialized (property can't be set via factory)
// This ensures all properties can be set through the factory method
var diagnostic = Diagnostic.Create(
MissingPropertyRule,
methodDeclaration.Identifier.GetLocation(),
namedType.Name,
property.Name
);
context.ReportDiagnostic(diagnostic);
}
}

Expand Down