Exemple #1
0
        private IBoundExpression ResolveLExpressionIsVariablePropertyOrFunction()
        {
            /*
             *
             *  <l-expression> is classified as a variable, a property or a function and one of the following is
             *  true:
             *      1. The declared type of <l-expression> is a UDT type or specific class, this type has an accessible
             *      member named <unrestricted-name>, <unrestricted-name> either does not specify a type
             *      character or specifies a type character whose associated type matches the declared type of
             *      the member, and one of the following is true:
             *
             *          1.1 The member is a variable, property or function. In this case, the member access expression
             *          is classified as a variable, property or function, respectively, refers to the member, and has
             *          the same declared type as the member.
             *
             *          1.2 The member is a subroutine. In this case, the member access expression is classified as a
             *          subroutine and refers to the member.
             *
             *
             *      2. The declared type of <l-expression> is Object or Variant. In this case, the member access
             *      expression is classified as an unbound member and has a declared type of Variant.
             */
            if (
                _lExpression.Classification != ExpressionClassification.Variable &&
                _lExpression.Classification != ExpressionClassification.Property &&
                _lExpression.Classification != ExpressionClassification.Function)
            {
                return(null);
            }
            var lExpressionDeclaration = _lExpression.ReferencedDeclaration;

            // The referenced declaration being null might mean that an index expression (e.g. an array with Variant elements) is used in a member access expression.
            // If it's an assignment for example we still have to bind the array (and not the element's referenced declaration) thus have to return the rest of the tree.
            // TODO: Find a better way of dealing with this, perhaps create declarations for Variant, Object etc.
            if (_lExpression.ReferencedDeclaration == null)
            {
                return(new MemberAccessExpression(null, ExpressionClassification.Unbound, _context, _unrestrictedNameContext, _lExpression));
            }
            var referencedType = lExpressionDeclaration.AsTypeDeclaration;

            if (referencedType == null)
            {
                return(null);
            }
            if (referencedType.DeclarationType != DeclarationType.UserDefinedType && referencedType.DeclarationType != DeclarationType.ClassModule)
            {
                return(null);
            }
            var udtMember = _declarationFinder.FindMemberWithParent(_project, _module, _parent, referencedType, _name, DeclarationType.UserDefinedTypeMember);

            if (udtMember != null)
            {
                return(new MemberAccessExpression(udtMember, ExpressionClassification.Variable, _context, _unrestrictedNameContext, _lExpression));
            }
            var variable = _declarationFinder.FindMemberWithParent(_project, _module, _parent, referencedType, _name, DeclarationType.Variable);

            if (variable != null)
            {
                return(new MemberAccessExpression(variable, ExpressionClassification.Variable, _context, _unrestrictedNameContext, _lExpression));
            }
            var property = _declarationFinder.FindMemberWithParent(_project, _module, _parent, referencedType, _name, _propertySearchType);

            if (property != null)
            {
                return(new MemberAccessExpression(property, ExpressionClassification.Property, _context, _unrestrictedNameContext, _lExpression));
            }
            var function = _declarationFinder.FindMemberWithParent(_project, _module, _parent, referencedType, _name, DeclarationType.Function);

            if (function != null)
            {
                return(new MemberAccessExpression(function, ExpressionClassification.Function, _context, _unrestrictedNameContext, _lExpression));
            }
            var subroutine = _declarationFinder.FindMemberWithParent(_project, _module, _parent, referencedType, _name, DeclarationType.Procedure);

            if (subroutine != null)
            {
                return(new MemberAccessExpression(subroutine, ExpressionClassification.Subroutine, _context, _unrestrictedNameContext, _lExpression));
            }
            // Assume that no match = failure on our side.
            return(CreateFailedExpression(_lExpression));
        }