protected override ICode VisitJsResolvedProperty(ExprJsResolvedProperty e) {
     if (e.Call.CallMethod != null) {
         var ctx = e.Ctx;
         var mDef = e.Call.CallMethod.Resolve();
         if (mDef.IsSetter) {
             var tRef = e.Call.CallMethod.Parameters.Last().ParameterType;
             var tDef = tRef.Resolve();
             var attr = tDef.GetCustomAttribute<JsStringEnumAttribute>();
             if (attr != null) {
                 var prop = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type = new ExprJsTypeVarName(ctx, tRef).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var value = e.Call.Args.Last().Named("value");
                 var js =  "prop = type.enumStringMap[value]";
                 var expr = new ExprJsExplicit(ctx, js, e.Type, type, enumStringMap, value, prop);
                 return expr;
             }
         } else {
             var tDef = e.Type.Resolve();
             var attr = tDef.GetCustomAttribute<JsStringEnumAttribute>();
             if (attr != null) {
                 var prop = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type = new ExprJsTypeVarName(ctx, e.Type).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var js = "type.enumStringMap[prop]";
                 var expr = new ExprJsExplicit(ctx, js, e.Type, prop, type, enumStringMap);
                 return expr;
             }
         }
     }
     return base.VisitJsResolvedProperty(e);
 }
 protected override ICode VisitJsResolvedProperty(ExprJsResolvedProperty e)
 {
     if (e.PropertyName == null)
     {
         // Indexer
         this.Visit(e.Call.Obj);
         this.js.Append("[");
         this.Visit(e.Call.Args.First());
         this.js.Append("]");
     }
     else
     {
         // Normal attribute/property
         if (e.Call.Obj != null)
         {
             this.Visit(e.Call.Obj);
             this.js.Append(".");
         }
         this.js.Append(e.PropertyName);
     }
     if (e.Call.CallMethod != null && e.Call.CallMethod.Resolve().IsSetter)
     {
         this.js.Append(" = ");
         this.Visit(e.Call.Args.Last());
     }
     return(e);
 }
        protected virtual ICode VisitJsResolvedProperty(ExprJsResolvedProperty e)
        {
            this.ThrowOnNoOverride();
            var call = this.HandleCall(e.Call, (obj, args) => new DupCall {
                ExprType      = e.Call.ExprType,
                CallMethod    = e.Call.CallMethod,
                IsVirtualCall = e.Call.IsVirtualCall,
                Obj           = obj,
                Args          = args,
                Type          = e.Call.Type,
                Ctx           = e.Call.Ctx,
            });

            if (call != e.Call)
            {
                return(new ExprJsResolvedProperty(e.Ctx, call, e.PropertyName));
            }
            else
            {
                return(e);
            }
        }
Beispiel #4
0
 protected override ICode VisitJsResolvedProperty(ExprJsResolvedProperty e)
 {
     if (e.Call.CallMethod != null)
     {
         var ctx  = e.Ctx;
         var mDef = e.Call.CallMethod.Resolve();
         if (mDef.IsSetter)
         {
             var tRef = e.Call.CallMethod.Parameters.Last().ParameterType;
             var tDef = tRef.Resolve();
             var attr = tDef.GetCustomAttribute <JsStringEnumAttribute>();
             if (attr != null)
             {
                 var prop          = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type          = new ExprJsTypeVarName(ctx, tRef).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var value         = e.Call.Args.Last().Named("value");
                 var js            = "prop = type.enumStringMap[value]";
                 var expr          = new ExprJsExplicit(ctx, js, e.Type, type, enumStringMap, value, prop);
                 return(expr);
             }
         }
         else
         {
             var tDef = e.Type.Resolve();
             var attr = tDef.GetCustomAttribute <JsStringEnumAttribute>();
             if (attr != null)
             {
                 var prop          = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type          = new ExprJsTypeVarName(ctx, e.Type).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var js            = "type.enumStringMap[prop]";
                 var expr          = new ExprJsExplicit(ctx, js, e.Type, prop, type, enumStringMap);
                 return(expr);
             }
         }
     }
     return(base.VisitJsResolvedProperty(e));
 }
 protected virtual ICode VisitJsResolvedProperty(ExprJsResolvedProperty e) {
     this.ThrowOnNoOverride();
     var call = this.HandleCall(e.Call, (obj, args) => new DupCall {
         ExprType = e.Call.ExprType,
         CallMethod = e.Call.CallMethod,
         IsVirtualCall = e.Call.IsVirtualCall,
         Obj = obj,
         Args = args,
         Type = e.Call.Type,
         Ctx = e.Call.Ctx,
     });
     if (call != e.Call) {
         return new ExprJsResolvedProperty(e.Ctx, call, e.PropertyName);
     } else {
         return e;
     }
 }
 protected override ICode VisitJsResolvedProperty(ExprJsResolvedProperty e) {
     if (e.PropertyName == null) {
         // Indexer
         this.Visit(e.Call.Obj);
         this.js.Append("[");
         this.Visit(e.Call.Args.First());
         this.js.Append("]");
     } else {
         // Normal attribute/property
         if (e.Call.Obj != null) {
             this.Visit(e.Call.Obj);
             this.js.Append(".");
         }
         this.js.Append(e.PropertyName);
     }
     if (e.Call.CallMethod != null && e.Call.CallMethod.Resolve().IsSetter) {
         this.js.Append(" = ");
         this.Visit(e.Call.Args.Last());
     }
     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;
 }
 protected override ICode VisitJsResolvedProperty(ExprJsResolvedProperty e) {
     this.code.Append(e.PropertyName);
     return e;
 }