Skip to content

Clean up route tooling for components #50651

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 12, 2023
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 @@ -7,30 +7,12 @@ internal sealed class RoutePatternOptions
{
private RoutePatternOptions() { }
public bool SupportTokenReplacement { get; private set; }
public bool SupportComplexSegments { get; private set; }
public bool SupportDefaultValues { get; private set; }
public bool SupportTwoAsteriskCatchAll { get; private set; }
public char[]? AdditionalInvalidParameterCharacters { get; private set; }

public static readonly RoutePatternOptions DefaultRoute = new RoutePatternOptions
{
SupportComplexSegments = true,
SupportDefaultValues = true,
SupportTwoAsteriskCatchAll = true,
};
public static readonly RoutePatternOptions DefaultRoute = new RoutePatternOptions();
public static readonly RoutePatternOptions ComponentsRoute = new RoutePatternOptions();

public static readonly RoutePatternOptions MvcAttributeRoute = new RoutePatternOptions
{
SupportComplexSegments = true,
SupportDefaultValues = true,
SupportTwoAsteriskCatchAll = true,
SupportTokenReplacement = true,
};

public static readonly RoutePatternOptions ComponentsRoute = new RoutePatternOptions
{
SupportComplexSegments = true,
SupportDefaultValues = true,
SupportTwoAsteriskCatchAll = true,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,71 +77,10 @@ private RoutePatternTree ParseTree()
ValidateNoConsecutiveSeparators(root, diagnostics);
ValidateCatchAllParameters(root, diagnostics);
ValidateParameterParts(root, diagnostics, routeParameters);
ValidateAdditionalInvalidParameterCharacters(root, diagnostics, _routePatternOptions);
ValidateComplexSegments(root, diagnostics, _routePatternOptions);

return new RoutePatternTree(_lexer.Text, root, diagnostics.ToImmutable(), routeParameters.ToImmutable());
}

private static void ValidateComplexSegments(RoutePatternCompilationUnit root, ImmutableArray<EmbeddedDiagnostic>.Builder diagnostics, RoutePatternOptions routePatternOptions)
{
if (routePatternOptions.SupportComplexSegments)
{
return;
}

foreach (var part in root)
{
if (part.TryGetNode(RoutePatternKind.Segment, out var segmentNode))
{
if (segmentNode.ChildCount > 1)
{
var message = $"Complex segment is not supported.";
diagnostics.Add(new EmbeddedDiagnostic(message, segmentNode.GetFullSpan()!.Value));
}
}
}
}

private static void ValidateAdditionalInvalidParameterCharacters(RoutePatternCompilationUnit root, ImmutableArray<EmbeddedDiagnostic>.Builder diagnostics, RoutePatternOptions routePatternOptions)
{
if (routePatternOptions.AdditionalInvalidParameterCharacters == null)
{
return;
}

foreach (var part in root)
{
if (part.TryGetNode(RoutePatternKind.Segment, out var segmentNode))
{
foreach (var segmentPart in segmentNode)
{
if (segmentPart.TryGetNode(RoutePatternKind.Parameter, out var parameterNode))
{
foreach (var parameterPart in parameterNode)
{
if (parameterPart.TryGetNode(RoutePatternKind.ParameterName, out var parameterNameNode))
{
var parameterNameToken = ((RoutePatternNameParameterPartNode)parameterNameNode).ParameterNameToken;
if (!parameterNameToken.IsMissing)
{
var name = parameterNameToken.Value!.ToString();
var invalidCharacter = name.IndexOfAny(routePatternOptions.AdditionalInvalidParameterCharacters);

if (invalidCharacter != -1)
{
var message = $"The character '{name[invalidCharacter]}' in parameter segment '{parameterNode}' is not allowed.";
diagnostics.Add(new EmbeddedDiagnostic(message, parameterNameNode.GetSpan()));
}
}
}
}
}
}
}
}
}

private static void ValidateStart(RoutePatternCompilationUnit root, IList<EmbeddedDiagnostic> diagnostics)
{
if (root.ChildCount > 1 &&
Expand Down Expand Up @@ -567,12 +506,6 @@ private ImmutableArray<RoutePatternParameterPartNode> ParseParameterParts()
RoutePatternKind.AsteriskToken,
VirtualCharSequence.FromBounds(firstAsteriskToken.VirtualChars, _currentToken.VirtualChars));

if (!_routePatternOptions.SupportTwoAsteriskCatchAll)
{
asterisksToken = asterisksToken.AddDiagnosticIfNone(
new EmbeddedDiagnostic("A catch-all parameter may only have one '*' at the beginning of the segment.", asterisksToken.GetFullSpan()!.Value));
}

parts.Add(new RoutePatternCatchAllParameterPartNode(asterisksToken));
ConsumeCurrentToken();
}
Expand Down Expand Up @@ -629,14 +562,6 @@ private RoutePatternDefaultValueParameterPartNode ParseDefaultValue()
var equalsToken = _currentToken;
var defaultValue = _lexer.TryScanDefaultValue() ?? CreateMissingToken(RoutePatternKind.DefaultValueToken);

if (!_routePatternOptions.SupportDefaultValues)
{
equalsToken = equalsToken.AddDiagnosticIfNone(
new EmbeddedDiagnostic(
"A parameter with a default value isn't supported.",
EmbeddedSyntaxHelpers.GetSpan(equalsToken, defaultValue)));
}

ConsumeCurrentToken();
var node = new RoutePatternDefaultValueParameterPartNode(equalsToken, defaultValue);
return node;
Expand Down