Example #1
0
        private static void ParseSignatureIntoMethod(VbMethod method, IReadOnlyList<IToken> signatureTokens)
        {
            TokenStreamReader tokenReader = new TokenStreamReader(signatureTokens);
            if (tokenReader.Peek().Type == TokenType.Symbol)
            {
                tokenReader.Read();
            }

            VbParameter parameter = new VbParameter();

            while (!tokenReader.IsEOF)
            {
                // If it's already the end of the signature, leave the loop.
                if (tokenReader.Peek().EqualsStringInvariant(")"))
                {
                    tokenReader.Read();
                    break;
                }

                IToken token = tokenReader.Read();

                if (IsParameterOptional(token))
                {
                    parameter.IsOptional = true;
                    continue;
                }

                VbParameterAccess access = VbParameterAccess.Default;
                if (IsParamaterAccessToken(token, out access))
                {
                    parameter.Access = access;
                    continue;
                }

                /* Assume that if the next parameter is "As", then this is a parameter name.
                 * Also watch out for implicit parameters, which are parameters that don't declare a type (variant).
                 */
                IToken peek = tokenReader.Peek();
                if (peek == null)
                {
                    break;
                }

                if (peek.EqualsStringInvariant("As") ||
                    peek.Type == TokenType.Symbol)
                {
                    parameter.Name = token.Content;
                    parameter.Location = token.Location;

                    if (peek.Type == TokenType.Symbol)
                    {
                        parameter.Type = VbTypes.Variant;

                        // Eat token.
                        tokenReader.Read();
                    }
                    else
                    {
                        // Eat token.
                        tokenReader.Read();

                        parameter.Type = new VbType()
                        {
                            TypeName = ReadUntilEOLIntoString(tokenReader, Delimiters)
                        };
                    }

                    /* Look ahead for an optional value declaration if this parameter is optional.
                     */
                    if (parameter.IsOptional)
                    {
                        if (tokenReader.GetPrevious().Content == "=")
                        {
                            parameter.OptionalDefaultValue = ReadUntilEOLIntoString(tokenReader, Delimiters);
                        }
                    }

                    /* Add parameter and reset instance.
                     */
                    method.AddParameter(parameter);

                    parameter = new VbParameter();

                    continue;
                }
            }

            /* Specify "void" return "type" in advance; may be overridden.
             */
            method.ReturnType = VbTypes.Void;

            bool canHaveReturnType = false;
            if (method.MethodKind == VbMethodType.Function)
            {
                canHaveReturnType = true;
            }
            else if (method.MethodKind == VbMethodType.Property)
            {
                IVbProperty property = (IVbProperty)method;
                if (property.Accessor == VbPropertyAccessor.Get)
                {
                    canHaveReturnType = true;
                }
            }

            /* Look for a return type.
             */
            if (canHaveReturnType)
            {
                method.ReturnType = VbTypes.Variant;

                if (!tokenReader.IsEOF)
                {
                    var returnTokens = tokenReader.GetUntilEOL().ToArray();
                    if (returnTokens[0].EqualsStringInvariant("As"))
                    {
                        string typeName = string.Concat(returnTokens.Skip(1).Select(_ => _.Content));
                        method.ReturnType = new VbType() { TypeName = typeName };
                    }
                }
            }
        }
Example #2
0
        internal static IEnumerable<IVbMethod> GetMethods(TokenStreamReader reader)
        {
            bool isInMethod = false;
            VbMethodType methodType = VbMethodType.Sub;

            // Remembers the complete signature for easier construction later.
            List<IToken> signatureTokens = new List<IToken>();

            IToken previous = null;
            VbMethod method = null;

            while (!reader.IsEOF)
            {
                if (!reader.IsBOF)
                {
                    previous = reader.GetPrevious();
                }

                IToken token = reader.Read();

                if (token.Type == TokenType.Word)
                {
                    if (token.EqualsStringInvariant(AnalyzerConstants.Method_Sub) ||
                        token.EqualsStringInvariant(AnalyzerConstants.Method_Function) ||
                        token.EqualsStringInvariant(AnalyzerConstants.Method_Property))
                    {
                        if (isInMethod)
                        {
                            if (previous.EqualsStringInvariant(AnalyzerConstants.End))
                            {
                                method.EndStatementLocation = token.Location;
                                isInMethod = false;
                            }

                            continue;
                        }

                        isInMethod = true;

                        methodType = (VbMethodType)Enum.Parse(typeof(VbMethodType), token.Content, true);

                        method = new VbMethod();

                        // Properties have Let/Get/Set next... eat that and store it.
                        if (methodType == VbMethodType.Property)
                        {
                            IToken propertyAcc = reader.Read();

                            method = new VbProperty()
                            {
                                Accessor = (VbPropertyAccessor)Enum.Parse(typeof(VbPropertyAccessor), propertyAcc.Content, true),
                            };
                        }

                        method.Visibility = MemberVisibility.Default;
                        method.Location = token.Location;
                        method.MethodKind = methodType;

                        /* Check if there was a visibility-modifier preceeding this method. If so, add it to our signature and correct source location to point to that token.
                         */
                        MemberVisibility visibility = MemberVisibility.Default;
                        if (TryGetMemberVisibility(previous, out visibility))
                        {
                            // Set method location to the previous token (start of line).
                            method.Location = previous.Location;
                        }

                        method.Visibility = visibility;
                        method.Name = reader.GetUntil(false, null, TokenType.Symbol).GetString();

                        signatureTokens.AddRange(reader.GetUntilEOL());

                        bool success = false;
                        try
                        {
                            ParseSignatureIntoMethod(method, signatureTokens);
                            success = true;
                        }
                        catch (Exception)
                        {
                            // FIXME: The parser may peek() too far beyond EOF. Need to handle that!
                        }

                        if (success)
                        {
                            yield return method;
                        }

                        signatureTokens.Clear();
                    }
                }
            }
        }