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)); }