public static Stmt IsWhiteSpace(Ctx ctx) {
     // See http://msdn.microsoft.com/en-us/library/t809ektx.aspx for list
     var whiteSpace = " \u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d\u0085\u00a0";
     var arg0 = ctx.MethodParameter(0);
     var c = new ExprJsResolvedMethod(ctx, ctx.String, null, "String.fromCharCode", arg0);
     var indexOf = new ExprJsResolvedMethod(ctx, ctx.Boolean, ctx.Literal(whiteSpace), "indexOf", c);
     return new StmtReturn(ctx,
         new ExprBinary(ctx, BinaryOp.GreaterThanOrEqual, ctx.Boolean, indexOf, ctx.Literal(0)));
 }
        protected virtual ICode VisitJsResolvedMethod(ExprJsResolvedMethod e)
        {
            this.ThrowOnNoOverride();
            var obj  = (Expr)this.Visit(e.Obj);
            var args = this.HandleList(e.Args, x => (Expr)this.Visit(x));

            if (obj != e.Obj || args != null)
            {
                return(new ExprJsResolvedMethod(e.Ctx, e.Type, obj, e.MethodName, args ?? e.Args));
            }
            else
            {
                return(e);
            }
        }
 protected override ICode VisitJsResolvedMethod(ExprJsResolvedMethod e)
 {
     if (e.Obj != null)
     {
         this.Visit(e.Obj);
         this.js.Append(".");
     }
     this.js.Append(e.MethodName);
     this.js.Append("(");
     if (e.Args.Any())
     {
         foreach (var arg in e.Args)
         {
             this.Visit(arg);
             this.js.Append(", ");
         }
         this.js.Length -= 2;
     }
     this.js.Append(")");
     return(e);
 }
 protected virtual ICode VisitJsResolvedMethod(ExprJsResolvedMethod e) {
     this.ThrowOnNoOverride();
     var obj = (Expr)this.Visit(e.Obj);
     var args = this.HandleList(e.Args, x => (Expr)this.Visit(x));
     if (obj != e.Obj || args != null) {
         return new ExprJsResolvedMethod(e.Ctx, e.Type, obj, e.MethodName, args ?? e.Args);
     } else {
         return e;
     }
 }
 public static Stmt GetHashCode(Ctx ctx) {
     var toString = new ExprJsResolvedMethod(ctx, ctx.String, ctx.This, "toExponential");
     var getHashCode = new ExprCall(ctx, typeof(string).GetMethod("GetHashCode"), toString);
     var stmt = new StmtReturn(ctx, getHashCode);
     return stmt;
 }
 protected override ICode VisitJsResolvedMethod(ExprJsResolvedMethod e) {
     if (e.Obj != null) {
         this.Visit(e.Obj);
         this.js.Append(".");
     }
     this.js.Append(e.MethodName);
     this.js.Append("(");
     if (e.Args.Any()) {
         foreach (var arg in e.Args) {
             this.Visit(arg);
             this.js.Append(", ");
         }
         this.js.Length -= 2;
     }
     this.js.Append(")");
     return e;
 }
 /// <summary>
 /// If a call/newobj requires translating to an Expr that is not a call/newobj, then it is done here.
 /// </summary>
 /// <param name="call"></param>
 /// <returns></returns>
 public static Expr ResolveCallSite(ICall call) {
     var ctx = call.Ctx;
     var mRef = call.CallMethod;
     var tRefDecl = mRef.DeclaringType;
     var mDef = mRef.Resolve();
     // A call to a method in a "JsClass" class - all external methods/properties require translating to JS
     var tDefDecl = mDef.DeclaringType;
     var jsClassAttr = tDefDecl.GetCustomAttribute<JsClassAttribute>() ?? tDefDecl.GetCustomAttribute<JsAbstractClassAttribute>();
     if (jsClassAttr != null) {
         if (mDef.IsExternal()) {
             var jsDetail = mDef.GetCustomAttribute<JsDetailAttribute>(true);
             var jsDetailName = jsDetail.NullThru(x => (string)x.Properties.FirstOrDefault(y => y.Name == "Name").Argument.Value);
             var jsDetailIsDomEventProp = jsDetail.NullThru(x => ((bool?)x.Properties.FirstOrDefault(y => y.Name == "IsDomEvent").Argument.Value) ?? false);
             if (mDef.IsGetter || mDef.IsSetter) {
                 // Property access
                 if (jsDetailIsDomEventProp) {
                     // Special handling of DOM events
                     if (!mDef.IsSetter) {
                         throw new InvalidOperationException("Only setters supported on DOM events");
                     }
                     if (!mDef.Name.StartsWith("set_On")) {
                         throw new InvalidOperationException("DOM event name must start with 'On'");
                     }
                     if (call.Args.Count() != 1) {
                         throw new InvalidOperationException("DOM event setter must have exactly one argument");
                     }
                     var eventName = jsDetailName ?? mDef.Name.Substring(6).ToLowerInvariant();
                     var eventNameExpr = ctx.Literal(eventName);
                     var safeCallFunction = (Action<object, string, Delegate>)InternalFunctions.SafeAddEventListener;
                     var safeCall = new ExprCall(ctx, safeCallFunction, null, call.Obj, eventNameExpr, call.Args.First());
                     return safeCall;
                 } else {
                     var propertyName = jsDetailName ?? JsCase(mDef.Name.Substring(4));
                     if (mDef.Name.Substring(4) == "Item") {
                         propertyName = null;
                     } else if (mDef.IsStatic) {
                         propertyName = JsCase(mDef.DeclaringType.Name) + "." + propertyName;
                     }
                     var jsProperty = new ExprJsResolvedProperty(ctx, call, propertyName);
                     return jsProperty;
                 }
             } else if (mDef.IsConstructor && !mDef.IsStatic) {
                 // Constructor new object call
                 var typeName = jsDetailName ?? (string)jsClassAttr.ConstructorArguments[0].Value;
                 var expr = new ExprJsResolvedCtor(ctx, typeName, tRefDecl, call.Args);
                 return expr;
             } else {
                 // Normal method call
                 var methodName = jsDetailName ?? JsCase(mDef.Name);
                 if (mDef.IsStatic) {
                     methodName = JsCase(mDef.DeclaringType.Name) + "." + methodName;
                 }
                 var expr = new ExprJsResolvedMethod(ctx, call.Type, call.Obj, methodName, call.Args);
                 return expr;
             }
         } else {
             return null;
         }
     }
     var jsRedirectAttr = mDef.GetCustomAttribute<JsRedirectAttribute>(true);
     if (jsRedirectAttr != null) {
         if (jsRedirectAttr.ConstructorArguments[0].Value == null) {
             return FindExprReturn(call, call.CallMethod.DeclaringType);
         }
         var redirectToTRef = ((TypeReference)jsRedirectAttr.ConstructorArguments[0].Value).FullResolve(mRef);
         var redirectToMRef = redirectToTRef.EnumResolvedMethods(mRef).First(x => x.MatchMethodOnly(mRef));
         switch (call.ExprType) {
         case Expr.NodeType.NewObj:
             return new ExprNewObj(ctx, redirectToMRef, call.Args);
         case Expr.NodeType.Call:
             return new ExprCall(ctx, redirectToMRef, call.Obj, call.Args, call.IsVirtualCall, null, call.Type);
         default:
             throw new NotImplementedException("Cannot handle: " + call.ExprType);
         }
     }
     var exprRet = FindExprReturn(call);
     if (exprRet != null) {
         return exprRet;
     }
     return null;
 }