Пример #1
0
        /// <summary>
        /// Type arguments for stacks are only valid on method declarations, and can have either '[' or '&lt;' as the
        /// starting character depending on output source.
        ///
        /// ex: MyNamespace.MyClass.MyMethod[T](T t)
        /// ex: MyNamespace.MyClass.MyMethod&lt;T&lt;(T t)
        ///
        /// Assumes the identifier "MyMethod" has already been parsed, and the type arguments will need to be parsed.
        /// </summary>
        private Result <StackFrameTypeArgumentList> TryParseTypeArguments()
        {
            if (!_lexer.ScanCurrentCharAsTokenIfMatch(
                    kind => kind is StackFrameKind.OpenBracketToken or StackFrameKind.LessThanToken,
                    out var openToken))
            {
                return(Result <StackFrameTypeArgumentList> .Empty);
            }

            var closeBracketKind = openToken.Kind is StackFrameKind.OpenBracketToken
                ? StackFrameKind.CloseBracketToken
                : StackFrameKind.GreaterThanToken;

            using var _ = ArrayBuilder <StackFrameNodeOrToken> .GetInstance(out var builder);

            var             currentIdentifier = _lexer.TryScanIdentifier(scanAtTrivia: false, scanLeadingWhitespace: true, scanTrailingWhitespace: true);
            StackFrameToken closeToken        = default;

            while (currentIdentifier.HasValue && currentIdentifier.Value.Kind == StackFrameKind.IdentifierToken)
            {
                builder.Add(new StackFrameIdentifierNameNode(currentIdentifier.Value));

                if (_lexer.ScanCurrentCharAsTokenIfMatch(closeBracketKind, out closeToken))
                {
                    break;
                }

                if (!_lexer.ScanCurrentCharAsTokenIfMatch(StackFrameKind.CommaToken, out var commaToken))
                {
                    return(Result <StackFrameTypeArgumentList> .Abort);
                }

                builder.Add(commaToken);
                currentIdentifier = _lexer.TryScanIdentifier();
            }

            if (builder.Count == 0)
            {
                return(Result <StackFrameTypeArgumentList> .Abort);
            }

            if (closeToken.IsMissing)
            {
                return(Result <StackFrameTypeArgumentList> .Abort);
            }

            var separatedList = new EmbeddedSeparatedSyntaxNodeList <StackFrameKind, StackFrameNode, StackFrameIdentifierNameNode>(builder.ToImmutable());

            return(new StackFrameTypeArgumentList(openToken, separatedList, closeToken));
        }
Пример #2
0
        /// <summary>
        /// MyNamespace.MyClass.MyMethod[|(string s1, string s2, int i1)|]
        /// Takes parameter declarations from method text and parses them into a <see cref="StackFrameParameterList"/>.
        /// </summary>
        /// <remarks>
        /// This method assumes that the caller requires method parameters, and returns null for all failure cases. The caller
        /// should escalate to abort parsing on null values.
        /// </remarks>
        private StackFrameParameterList?TryParseRequiredMethodParameters()
        {
            if (!_lexer.ScanCurrentCharAsTokenIfMatch(StackFrameKind.OpenParenToken, scanTrailingWhitespace: true, out var openParen))
            {
                return(null);
            }

            if (_lexer.ScanCurrentCharAsTokenIfMatch(StackFrameKind.CloseParenToken, out var closeParen))
            {
                return(new(openParen, EmbeddedSeparatedSyntaxNodeList <StackFrameKind, StackFrameNode, StackFrameParameterDeclarationNode> .Empty, closeParen));
            }

            using var _ = ArrayBuilder <StackFrameNodeOrToken> .GetInstance(out var builder);

            while (true)
            {
                var(success, parameterNode) = ParseParameterNode();
                if (!success)
                {
                    return(null);
                }

                RoslynDebug.AssertNotNull(parameterNode);
                builder.Add(parameterNode);

                if (!_lexer.ScanCurrentCharAsTokenIfMatch(StackFrameKind.CommaToken, out var commaToken))
                {
                    break;
                }

                builder.Add(commaToken);
            }

            if (!_lexer.ScanCurrentCharAsTokenIfMatch(StackFrameKind.CloseParenToken, out closeParen))
            {
                return(null);
            }

            var parameters = new EmbeddedSeparatedSyntaxNodeList <StackFrameKind, StackFrameNode, StackFrameParameterDeclarationNode>(builder.ToImmutable());

            return(new(openParen, parameters, closeParen));
        }