Ejemplo n.º 1
0
    private RoutePatternParameterPart ParseParameter(string routeParameter)
    {
        // See: #475 - these tests don't pass the 'whole' text.
        var templatePart = RouteParameterParser.ParseRouteParameter(routeParameter);

        return(templatePart);
    }
Ejemplo n.º 2
0
    private static bool ParseParameter(Context context, List <RoutePatternPart> parts)
    {
        Debug.Assert(context.Current == OpenBrace);
        context.Mark();

        context.MoveNext();

        while (true)
        {
            if (context.Current == OpenBrace)
            {
                // This is an open brace inside of a parameter, it has to be escaped
                if (context.MoveNext())
                {
                    if (context.Current != OpenBrace)
                    {
                        // If we see something like "{p1:regex(^\d{3", we will come here.
                        context.Error = Resources.TemplateRoute_UnescapedBrace;
                        return(false);
                    }
                }
                else
                {
                    // This is a dangling open-brace, which is not allowed
                    // Example: "{p1:regex(^\d{"
                    context.Error = Resources.TemplateRoute_MismatchedParameter;
                    return(false);
                }
            }
            else if (context.Current == CloseBrace)
            {
                // When we encounter Closed brace here, it either means end of the parameter or it is a closed
                // brace in the parameter, in that case it needs to be escaped.
                // Example: {p1:regex(([}}])\w+}. First pair is escaped one and last marks end of the parameter
                if (!context.MoveNext())
                {
                    // This is the end of the string -and we have a valid parameter
                    break;
                }

                if (context.Current == CloseBrace)
                {
                    // This is an 'escaped' brace in a parameter name
                }
                else
                {
                    // This is the end of the parameter
                    break;
                }
            }

            if (!context.MoveNext())
            {
                // This is a dangling open-brace, which is not allowed
                context.Error = Resources.TemplateRoute_MismatchedParameter;
                return(false);
            }
        }

        var text = context.Capture();

        if (text == "{}")
        {
            context.Error = Resources.FormatTemplateRoute_InvalidParameterName(string.Empty);
            return(false);
        }

        var inside  = text.Substring(1, text.Length - 2);
        var decoded = inside.Replace("}}", "}").Replace("{{", "{");

        // At this point, we need to parse the raw name for inline constraint,
        // default values and optional parameters.
        var templatePart = RouteParameterParser.ParseRouteParameter(decoded);

        // See #475 - this is here because InlineRouteParameterParser can't return errors
        if (decoded.StartsWith("*", StringComparison.Ordinal) && decoded.EndsWith("?", StringComparison.Ordinal))
        {
            context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional;
            return(false);
        }

        if (templatePart.IsOptional && templatePart.Default != null)
        {
            // Cannot be optional and have a default value.
            // The only way to declare an optional parameter is to have a ? at the end,
            // hence we cannot have both default value and optional parameter within the template.
            // A workaround is to add it as a separate entry in the defaults argument.
            context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue;
            return(false);
        }

        var parameterName = templatePart.Name;

        if (IsValidParameterName(context, parameterName))
        {
            parts.Add(templatePart);
            return(true);
        }
        else
        {
            return(false);
        }
    }