Skip to content

Commit 066dc47

Browse files
Copilotjongalloway
andcommitted
Fix dead code, improve error messages, and update CanParse in Mermaid parser
- Add MermaidDiagramKind.Unknown for recognized-but-unsupported Mermaid types - Update TryDetectKind to return Unknown for known Mermaid keywords (sequenceDiagram, classDiagram, gantt, etc.) so they bypass the generic error and reach MermaidParser - Fix dead null-parser guard in MermaidParser.Parse: now reachable for Unknown kind, emitting an informative message with the concrete type token - Update MermaidParser.CanParse to check registered parsers (returns false for Unknown) - Differentiate MermaidDocument.Parse error messages: whitespace vs. comment-only vs. unrecognized type - Remove redundant `document is not null` guard; add [NotNullWhen(true)] to TryParse - Use IndexOf/slice instead of Split for first-token extraction (avoids array allocation) Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
1 parent 564e1c5 commit 066dc47

3 files changed

Lines changed: 57 additions & 5 deletions

File tree

src/DiagramForge/Parsers/Mermaid/MermaidDiagramKind.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ namespace DiagramForge.Parsers.Mermaid;
22

33
internal enum MermaidDiagramKind
44
{
5+
Unknown,
56
Flowchart,
67
}

src/DiagramForge/Parsers/Mermaid/MermaidDocument.cs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ private MermaidDocument(MermaidDiagramKind kind, string headerLine, string[] lin
1717

1818
public string[] Lines { get; }
1919

20-
public static bool TryParse(string diagramText, out MermaidDocument? document)
20+
public static bool TryParse(string diagramText, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out MermaidDocument? document)
2121
{
2222
document = null;
2323
if (string.IsNullOrWhiteSpace(diagramText))
@@ -40,12 +40,50 @@ public static bool TryParse(string diagramText, out MermaidDocument? document)
4040
return true;
4141
}
4242

43+
// Known Mermaid diagram-type keywords (lowercased) that are recognized but not yet
44+
// supported by any registered IMermaidDiagramParser. Detecting them as Unknown lets
45+
// MermaidParser emit a specific "unsupported type" error instead of a generic one.
46+
private static readonly HashSet<string> KnownUnsupportedMermaidKeywords = new(StringComparer.Ordinal)
47+
{
48+
"sequencediagram",
49+
"classdiagram",
50+
"statediagram",
51+
"statediagram-v2",
52+
"erdiagram",
53+
"journey",
54+
"gantt",
55+
"pie",
56+
"gitgraph",
57+
"mindmap",
58+
"timeline",
59+
"quadrantchart",
60+
"requirementdiagram",
61+
"block-beta",
62+
"packet-beta",
63+
"architecture-beta",
64+
"kanban",
65+
"sankey-beta",
66+
"xychart-beta",
67+
"zenuml",
68+
};
69+
4370
public static MermaidDocument Parse(string diagramText)
4471
{
45-
if (TryParse(diagramText, out var document) && document is not null)
72+
if (TryParse(diagramText, out var document))
4673
return document;
4774

48-
throw new DiagramParseException("Diagram text cannot be null, empty, or an unsupported Mermaid diagram type.");
75+
if (string.IsNullOrWhiteSpace(diagramText))
76+
throw new DiagramParseException("Diagram text cannot be null or whitespace.");
77+
78+
var firstContentLine = diagramText
79+
.Split('\n')
80+
.Select(line => line.Trim())
81+
.FirstOrDefault(line => !string.IsNullOrEmpty(line) && !line.StartsWith("%%", StringComparison.Ordinal));
82+
83+
if (firstContentLine is null)
84+
throw new DiagramParseException("Diagram text cannot be empty or contain only comments.");
85+
86+
throw new DiagramParseException($"Unsupported Mermaid diagram type '{firstContentLine}'.");
4987
}
5088

5189
private static bool TryDetectKind(string headerLine, out MermaidDiagramKind kind)
@@ -60,6 +98,14 @@ private static bool TryDetectKind(string headerLine, out MermaidDiagramKind kind
6098
return true;
6199
}
62100

101+
var spaceIndex = normalizedHeader.IndexOf(' ');
102+
var keyword = spaceIndex >= 0 ? normalizedHeader[..spaceIndex] : normalizedHeader;
103+
if (KnownUnsupportedMermaidKeywords.Contains(keyword))
104+
{
105+
kind = MermaidDiagramKind.Unknown;
106+
return true;
107+
}
108+
63109
kind = default;
64110
return false;
65111
}

src/DiagramForge/Parsers/Mermaid/MermaidParser.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ public sealed class MermaidParser : IDiagramParser
2626
/// <inheritdoc/>
2727
public bool CanParse(string diagramText)
2828
{
29-
return MermaidDocument.TryParse(diagramText, out _);
29+
if (!MermaidDocument.TryParse(diagramText, out var document))
30+
return false;
31+
32+
return _diagramParsers.Any(p => p.CanParse(document.Kind));
3033
}
3134

3235
/// <inheritdoc/>
@@ -36,8 +39,10 @@ public Diagram Parse(string diagramText)
3639
var parser = _diagramParsers.FirstOrDefault(candidate => candidate.CanParse(document.Kind));
3740
if (parser is null)
3841
{
42+
var spaceIndex = document.HeaderLine.IndexOf(' ');
43+
var diagramTypeToken = spaceIndex >= 0 ? document.HeaderLine[..spaceIndex] : document.HeaderLine;
3944
throw new DiagramParseException(
40-
$"Mermaid diagram type '{document.Kind}' is not supported. " +
45+
$"Unsupported Mermaid diagram type '{diagramTypeToken}'. " +
4146
$"Supported Mermaid types: {string.Join(", ", SupportedDiagramTypes)}");
4247
}
4348

0 commit comments

Comments
 (0)