static TypeInfo getType(CompilerContext context, ExpressionNode expression) {
            if (ValidationHelper.isMethod(expression)) {
                throw context.error(CompileErrorId.UnexpectedMethodReference, expression);
            }
            var info = expression.getUserData(typeof(ExpressionInfo));
            if (info.Type != null) {
                return info.Type;
            } else if (info.IsConstant) {
                context.ConstantBuilder.buildConstant(expression);
                return info.Type;
            } else if (info.Members != null) {
                foreach (var member in info.Members) {
                    switch (member.MemberKind) {
                    case Field:
                        var field = member.Field;
                        if (field.Value != null) {
                            info.IsConstant = true;
                            info.Value = field.Value;
                        }
                        info.Member = member;
                        info.Type = member.Type;
                        if (!isInDeprecatedContext(context)) {
							if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, field)) {
								context.addWarning(CompileErrorId.DeprecatedField, expression,
										BytecodeHelper.getDisplayName(field.DeclaringType), field.Name);
							}
                        }
						if (context.CodeValidationContext.IsInMethod && context.CodeValidationContext.IsInLambda) {
	                    	if (!member.IsStatic && expression.ExpressionKind == ExpressionKind.SimpleName) {
				                var typeBuilder = context.LambdaScopes[context.CodeValidationContext.RootMethod];
				                if (typeBuilder.getField("this$0") == null) {
				                    typeBuilder.defineField("this$0", context.CurrentType);
				                }
	                    	}
                    	}
                        return member.Type;
                        
                    case Type:
                        info.Member = member;
                        info.Type = member.Type;
                        if (!isInDeprecatedContext(context)) {
							if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, info.Type)) {
								context.addWarning(CompileErrorId.DeprecatedType, expression,
										BytecodeHelper.getDisplayName(info.Type));
							}
						}
                        return member.Type;
						
                    case Indexer:
                    case Property:
                        info.Member = member;
                        info.Type = member.Type;
                        if (!isInDeprecatedContext(context)) {
							if (member.GetAccessor != null) {
								if (member.SetAccessor == null) {
									if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.GetAccessor)) {
										context.addWarning(CompileErrorId.DeprecatedProperty, expression,
												BytecodeHelper.getDisplayName(member.DeclaringType), member.Name);
									}
								} else {
									if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.GetAccessor) &&
											BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.SetAccessor)) {
										context.addWarning(CompileErrorId.DeprecatedProperty, expression,
												BytecodeHelper.getDisplayName(member.DeclaringType), member.Name);
									}
								}
							} else if (member.SetAccessor != null) {
								if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.SetAccessor)) {
									context.addWarning(CompileErrorId.DeprecatedProperty, expression,
											BytecodeHelper.getDisplayName(member.DeclaringType), member.Name);
								}
							}
						}
						if (context.CodeValidationContext.IsInMethod && context.CodeValidationContext.IsInLambda) {
	                    	if (!member.IsStatic && expression.ExpressionKind == ExpressionKind.SimpleName) {
				                var typeBuilder = context.LambdaScopes[context.CodeValidationContext.RootMethod];
				                if (typeBuilder.getField("this$0") == null) {
				                    typeBuilder.defineField("this$0", context.CurrentType);
				                }
	                    	}
                    	}
                        return member.Type;
                        
                    case Local:
						if (context.CodeValidationContext.IsInMethod) {
	                        var currentMethod = context.CodeValidationContext.CurrentMethod;
	                      	var currentType = (TypeBuilder)currentMethod.DeclaringType;
	                        if (currentType.FullName.indexOf('#') == -1 && context.CodeValidationContext.IsInLambda) {
		                        if (currentMethod != member.Method) {
		                            member.IsUsedFromLambda = true;
					                var typeBuilder = context.LambdaScopes[context.CodeValidationContext.RootMethod];
					                context.getLocalField(typeBuilder, (LocalMemberInfo)member);
		                        }
	                        }
                        }
                        info.Member = member;
                        info.Type = member.Type;
                        return member.Type;
                        
                    default:
                        break;
                    }
                }
                if (info.ExtensionMethods != null && info.ExtensionMethods.any()) {
                    return info.Type = info.ExtensionMethods.first().Parameters.first().Type;
                }
            }
            throw new Exception("Internal error line " + (expression.getLine() + 1));
        }