diff --git a/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs b/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs index c322296..541c1d8 100644 --- a/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs +++ b/Semantics.SourceGenerators/Generators/QuantitiesGenerator.cs @@ -20,6 +20,14 @@ namespace Semantics.SourceGenerators; [Generator] public class QuantitiesGenerator : GeneratorBase { + private static readonly DiagnosticDescriptor UnknownDimensionReference = new( + id: "SEM001", + title: "Unknown dimension reference in physics relationship", + messageFormat: "Dimension '{0}' references unknown dimension '{1}' in {2}; the operator will not be generated. Check spelling and that the referenced dimension exists in dimensions.json.", + category: "Semantics.SourceGenerators", + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + public QuantitiesGenerator() : base("dimensions.json") { } protected override void Generate(SourceProductionContext context, DimensionsMetadata metadata, CodeBlocker codeBlocker) @@ -32,8 +40,8 @@ protected override void Generate(SourceProductionContext context, DimensionsMeta // Phase A: Build maps and collect operators Dictionary dimensionMap = BuildDimensionMap(metadata); Dictionary typeFormMap = BuildTypeFormMap(metadata); - List allOperators = CollectAllOperators(metadata, dimensionMap); - List allProducts = CollectAllProducts(metadata, dimensionMap); + List allOperators = CollectAllOperators(context, metadata, dimensionMap); + List allProducts = CollectAllProducts(context, metadata, dimensionMap); Dictionary> operatorsByOwner = GroupBy(allOperators, o => o.OwnerTypeName); Dictionary> productsByOwner = GroupBy(allProducts, p => p.SelfTypeName); @@ -112,7 +120,7 @@ private static Dictionary BuildTypeFormMap(DimensionsMetadata metad return map; } - private static List CollectAllOperators(DimensionsMetadata metadata, Dictionary dimMap) + private static List CollectAllOperators(SourceProductionContext context, DimensionsMetadata metadata, Dictionary dimMap) { HashSet seen = []; List result = []; @@ -124,11 +132,13 @@ private static List CollectAllOperators(DimensionsMetadata metadat { if (!dimMap.TryGetValue(integral.Other, out PhysicalDimension? otherDim)) { + ReportUnknownReference(context, dim.Name, integral.Other, $"integrals[{integral.Other} -> {integral.Result}].other"); continue; } if (!dimMap.TryGetValue(integral.Result, out PhysicalDimension? resultDim)) { + ReportUnknownReference(context, dim.Name, integral.Result, $"integrals[{integral.Other} -> {integral.Result}].result"); continue; } @@ -168,11 +178,13 @@ private static List CollectAllOperators(DimensionsMetadata metadat { if (!dimMap.TryGetValue(derivative.Other, out PhysicalDimension? otherDim)) { + ReportUnknownReference(context, dim.Name, derivative.Other, $"derivatives[{derivative.Other} -> {derivative.Result}].other"); continue; } if (!dimMap.TryGetValue(derivative.Result, out PhysicalDimension? resultDim)) { + ReportUnknownReference(context, dim.Name, derivative.Result, $"derivatives[{derivative.Other} -> {derivative.Result}].result"); continue; } @@ -205,7 +217,7 @@ private static List CollectAllOperators(DimensionsMetadata metadat return result; } - private static List CollectAllProducts(DimensionsMetadata metadata, Dictionary dimMap) + private static List CollectAllProducts(SourceProductionContext context, DimensionsMetadata metadata, Dictionary dimMap) { HashSet seen = []; List result = []; @@ -217,11 +229,13 @@ private static List CollectAllProducts(DimensionsMetadata metadata, { if (!dimMap.TryGetValue(dot.Other, out PhysicalDimension? otherDim)) { + ReportUnknownReference(context, dim.Name, dot.Other, $"dotProducts[{dot.Other} -> {dot.Result}].other"); continue; } if (!dimMap.TryGetValue(dot.Result, out PhysicalDimension? resultDim)) { + ReportUnknownReference(context, dim.Name, dot.Result, $"dotProducts[{dot.Other} -> {dot.Result}].result"); continue; } @@ -255,11 +269,13 @@ private static List CollectAllProducts(DimensionsMetadata metadata, { if (!dimMap.TryGetValue(cross.Other, out PhysicalDimension? otherDim)) { + ReportUnknownReference(context, dim.Name, cross.Other, $"crossProducts[{cross.Other} -> {cross.Result}].other"); continue; } if (!dimMap.TryGetValue(cross.Result, out PhysicalDimension? resultDim)) { + ReportUnknownReference(context, dim.Name, cross.Result, $"crossProducts[{cross.Other} -> {cross.Result}].result"); continue; } @@ -297,6 +313,16 @@ private static void AddOp(List list, HashSet seen, string } } + private static void ReportUnknownReference(SourceProductionContext context, string owningDimension, string unknownReference, string fieldPath) + { + context.ReportDiagnostic(Diagnostic.Create( + UnknownDimensionReference, + Location.None, + owningDimension, + unknownReference, + fieldPath)); + } + private static Dictionary> GroupBy(List items, Func keySelector) { Dictionary> groups = [];