/// <summary>
        /// Parses a <see cref="StackFrameNameNode"/> which could either be a <see cref="StackFrameSimpleNameNode"/> or <see cref="StackFrameQualifiedNameNode" />.
        ///
        /// Nodes will be parsed for arity but not generic type arguments.
        ///
        /// <code>
        /// All of the following are valid nodes, where "$$" marks the parsing starting point, and "[|" + "|]" mark the endpoints of the parsed node excluding trivia
        ///   * [|$$MyNamespace.MyClass.MyMethod|](string s)
        ///   * MyClass.MyMethod([|$$string|] s)
        ///   * MyClass.MyMethod([|$$string[]|] s)
        ///   * [|$$MyClass`1.MyMethod|](string s)
        ///   * [|$$MyClass.MyMethod|][T](T t)
        /// </code>
        ///
        /// </summary>
        private StackFrameNameNode?TryParseRequiredNameNode(bool scanAtTrivia)
        {
            var currentIdentifer = _lexer.TryScanIdentifier(scanAtTrivia: scanAtTrivia, scanLeadingWhitespace: true, scanTrailingWhitespace: false);

            if (!currentIdentifer.HasValue)
            {
                return(null);
            }

            var(success, genericIdentifier) = TryScanGenericTypeIdentifier(currentIdentifer.Value);
            if (!success)
            {
                return(null);
            }

            RoslynDebug.AssertNotNull(genericIdentifier);
            StackFrameNameNode nameNode = genericIdentifier;

            while (true)
            {
                (success, var memberAccess) = TryParseQualifiedName(nameNode);
                if (!success)
                {
                    return(null);
                }

                if (memberAccess is null)
                {
                    Debug.Assert(nameNode is StackFrameQualifiedNameNode or StackFrameSimpleNameNode);
                    return(nameNode);
                }

                nameNode = memberAccess;
            }
        }
Beispiel #2
0
        public StackFrameQualifiedNameNode(StackFrameNameNode left, StackFrameToken dotToken, StackFrameSimpleNameNode right) : base(StackFrameKind.MemberAccess)
        {
            Debug.Assert(dotToken.Kind == StackFrameKind.DotToken);

            Left     = left;
            DotToken = dotToken;
            Right    = right;
        }
Beispiel #3
0
        /// <summary>
        /// Given an existing left hand side node or token, parse a qualified name if possible. Returns
        /// null with success if a dot token is not available
        /// </summary>
        private Result <StackFrameQualifiedNameNode> TryParseQualifiedName(StackFrameNameNode lhs)
        {
            if (!_lexer.ScanCurrentCharAsTokenIfMatch(StackFrameKind.DotToken, out var dotToken))
            {
                return(Result <StackFrameQualifiedNameNode> .Empty);
            }

            var identifier = _lexer.TryScanIdentifier();

            if (!identifier.HasValue)
            {
                return(Result <StackFrameQualifiedNameNode> .Abort);
            }

            var(success, rhs) = TryScanGenericTypeIdentifier(identifier.Value);
            if (!success)
            {
                return(Result <StackFrameQualifiedNameNode> .Abort);
            }

            RoslynDebug.AssertNotNull(rhs);
            return(new StackFrameQualifiedNameNode(lhs, dotToken, rhs));
        }
        /// <summary>
        /// Given an existing left hand side node or token, parse a qualified name if possible. Returns
        /// null with success if a dot token is not available
        /// </summary>
        private Result <StackFrameQualifiedNameNode> TryParseQualifiedName(StackFrameNameNode lhs)
        {
            if (!_lexer.ScanCurrentCharAsTokenIfMatch(StackFrameKind.DotToken, out var dotToken))
            {
                return(Result <StackFrameQualifiedNameNode> .Empty);
            }

            // Check if this is a generated identifier
            (var success, StackFrameSimpleNameNode? rhs) = TryScanGeneratedName();
            if (!success)
            {
                return(Result <StackFrameQualifiedNameNode> .Abort);
            }

            if (rhs is not null)
            {
                return(new StackFrameQualifiedNameNode(lhs, dotToken, rhs));
            }

            // The identifier is not a generated name, parse as a normal identifier and check for generics
            var identifier = _lexer.TryScanIdentifier();

            if (!identifier.HasValue)
            {
                return(Result <StackFrameQualifiedNameNode> .Abort);
            }

            (success, rhs) = TryScanGenericTypeIdentifier(identifier.Value);

            if (!success)
            {
                return(Result <StackFrameQualifiedNameNode> .Abort);
            }

            RoslynDebug.AssertNotNull(rhs);
            return(new StackFrameQualifiedNameNode(lhs, dotToken, rhs));
        }