From f174f7c996794ac40cb608da92a9b8a439b060c6 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 5 Oct 2023 19:32:30 +0200 Subject: [PATCH] More diags --- .../Api/Diagnostics/Diagnostic_Builder.cs | 2 +- .../Internal/FlowAnalysis/DecisionTree.cs | 17 ++++++++++++++++- .../FlowAnalysis/MatchExhaustiveness.cs | 16 ++++++++++++---- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Draco.Compiler/Api/Diagnostics/Diagnostic_Builder.cs b/src/Draco.Compiler/Api/Diagnostics/Diagnostic_Builder.cs index 4166f0217..3b53d6107 100644 --- a/src/Draco.Compiler/Api/Diagnostics/Diagnostic_Builder.cs +++ b/src/Draco.Compiler/Api/Diagnostics/Diagnostic_Builder.cs @@ -69,7 +69,7 @@ public Builder WithFormatArgs(params object?[] args) return this; } - public Builder WithLocation(Location location) + public Builder WithLocation(Location? location) { this.Location = location; return this; diff --git a/src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs b/src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs index 195e811f1..15199d394 100644 --- a/src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs +++ b/src/Draco.Compiler/Internal/FlowAnalysis/DecisionTree.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -269,6 +270,15 @@ private SpecializationComparer() _ => null, }; + // TODO: Doc + private static BoundPattern? ConstructUnhandledPattern(INode node) + { + if (node.NotCovered is null) return null; + + // TODO: Wrap in parent + return node.NotCovered; + } + /// /// The root node of this tree. /// @@ -291,7 +301,12 @@ private SpecializationComparer() /// /// An example of an unhandled pattern, if any. /// - public BoundPattern? UnhandledExample => throw new NotImplementedException(); + public BoundPattern? UnhandledExample => GraphTraversal + .DepthFirst(this.Root, n => n.Children.Select(c => c.Value)) + .Where(n => n.IsFail) + .Select(ConstructUnhandledPattern) + .OfType() + .FirstOrDefault(); private readonly IntrinsicSymbols intrinsicSymbols; private readonly HashSet usedActions = new(); diff --git a/src/Draco.Compiler/Internal/FlowAnalysis/MatchExhaustiveness.cs b/src/Draco.Compiler/Internal/FlowAnalysis/MatchExhaustiveness.cs index 46bc6e41b..20971eca2 100644 --- a/src/Draco.Compiler/Internal/FlowAnalysis/MatchExhaustiveness.cs +++ b/src/Draco.Compiler/Internal/FlowAnalysis/MatchExhaustiveness.cs @@ -48,11 +48,19 @@ public override void VisitMatchExpression(BoundMatchExpression node) if (!decisionTree.IsExhaustive) { - // TODO: Add example // Report - this.diagnostics.Add(Diagnostic.Create( - template: FlowAnalysisErrors.NonExhaustiveMatchExpression, - location: node.Syntax?.Location)); + var diagBuilder = Diagnostic.CreateBuilder() + .WithTemplate(FlowAnalysisErrors.NonExhaustiveMatchExpression) + .WithLocation(node.Syntax?.Location); + var example = decisionTree.UnhandledExample; + if (example is not null) + { + diagBuilder.WithRelatedInformation(DiagnosticRelatedInformation.Create( + location: node.Syntax?.Location, + format: "for example, the pattern {0} is not handled", + formatArgs: DecisionTree.ToDisplayString(example))); + } + this.diagnostics.Add(diagBuilder.Build()); } foreach (var (covers, redundant) in decisionTree.Redundancies)