protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context) { var rr = this.Emitter.Resolver.ResolveNode(context, this.Emitter); var oldLifting = this.Emitter.ForbidLifting; this.Emitter.ForbidLifting = false; var analyzer = new CaptureAnalyzer(this.Emitter); analyzer.Analyze(this.Body, this.Parameters.Select(p => p.Name)); var oldLevel = this.Emitter.Level; if (analyzer.UsedVariables.Count == 0) { this.Emitter.ResetLevel(); Indent(); } AsyncBlock asyncBlock = null; this.PushLocals(); if (this.IsAsync) { if (context is LambdaExpression) { asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context); } else { asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context); } asyncBlock.InitAsyncBlock(); } var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(parameters, body); bool block = body is BlockStatement; this.Write(""); var savedPos = this.Emitter.Output.Length; var savedThisCount = this.Emitter.ThisRefCounter; var capturedVariables = this.GetCapturedLoopVariables(); if (capturedVariables != null && capturedVariables.Length > 0) { this.Write("(function (" + string.Join(", ", capturedVariables) + ") "); this.BeginBlock(); this.Write("return "); } this.WriteFunction(); this.EmitMethodParameters(parameters, null, context); this.WriteSpace(); int pos = 0; if (!block && !this.IsAsync) { this.BeginBlock(); pos = this.Emitter.Output.Length; } bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync; if (isSimpleLambda) { this.ConvertParamsToReferences(parameters); var lrr = rr as LambdaResolveResult; if (lrr == null || lrr.ReturnType.Kind != TypeKind.Void) { this.WriteReturn(true); } } if (this.IsAsync) { asyncBlock.Emit(true); } else { body.AcceptVisitor(this.Emitter); } if (isSimpleLambda) { this.WriteSemiColon(); } if (!block && !this.IsAsync) { this.WriteNewLine(); this.EndBlock(); } if (!block && !this.IsAsync) { this.EmitTempVars(pos); } if (analyzer.UsedVariables.Count == 0) { if (!this.Emitter.ForbidLifting) { var name = "f" + (this.Emitter.NamedFunctions.Count + 1); var code = this.Emitter.Output.ToString().Substring(savedPos); var pair = this.Emitter.NamedFunctions.FirstOrDefault(p => p.Value == code); if (pair.Key != null && pair.Value != null) { name = pair.Key; } else { this.Emitter.NamedFunctions.Add(name, code); } this.Emitter.Output.Remove(savedPos, this.Emitter.Output.Length - savedPos); this.Emitter.Output.Insert(savedPos, JS.Vars.D_ + "." + BridgeTypes.ToJsName(this.Emitter.TypeInfo.Type, this.Emitter, true) + "." + name); } this.Emitter.ResetLevel(oldLevel); } this.Emitter.ForbidLifting = oldLifting; var methodDeclaration = this.Body.GetParent <MethodDeclaration>(); if (this.Emitter.ThisRefCounter > savedThisCount || this.IsAsync && methodDeclaration != null && !methodDeclaration.HasModifier(Modifiers.Static)) { this.Emitter.Output.Insert(savedPos, JS.Funcs.BRIDGE_BIND + "(this, "); this.WriteCloseParentheses(); } if (capturedVariables != null && capturedVariables.Length > 0) { this.WriteSemiColon(true); this.EndBlock(); this.Write(")(" + string.Join(", ", capturedVariables) + ")"); } this.PopLocals(); this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); }
protected virtual void WriteObjectInitializer(IEnumerable <Expression> expressions, bool changeCase, TypeDefinition type) { bool needComma = false; List <string> names = new List <string>(); if (expressions != null) { foreach (Expression item in expressions) { NamedExpression namedExression = item as NamedExpression; NamedArgumentExpression namedArgumentExpression = item as NamedArgumentExpression; if (needComma) { this.WriteComma(); } needComma = true; string name = namedExression != null ? namedExression.Name : namedArgumentExpression.Name; if (changeCase) { name = Object.Net.Utilities.StringUtils.ToLowerCamelCase(name); } Expression expression = namedExression != null ? namedExression.Expression : namedArgumentExpression.Expression; this.Write(name, ": "); expression.AcceptVisitor(this.Emitter); names.Add(name); } } if (this.Emitter.Validator.IsObjectLiteral(type) && !this.Emitter.Validator.IsIgnoreType(type)) { var key = BridgeTypes.GetTypeDefinitionKey(type); var tinfo = this.Emitter.Types.FirstOrDefault(t => t.Key == key); if (tinfo != null) { var members = tinfo.InstanceConfig.Fields.Concat(tinfo.InstanceConfig.Properties); if (members.Any()) { foreach (var member in members) { var name = member.GetName(this.Emitter); if (changeCase) { name = Object.Net.Utilities.StringUtils.ToLowerCamelCase(name); } if (names.Contains(name)) { continue; } if (needComma) { this.WriteComma(); } needComma = true; this.Write(name, ": "); var primitiveExpr = member.Initializer as PrimitiveExpression; if (primitiveExpr != null && primitiveExpr.Value is AstType) { this.Write("new " + BridgeTypes.ToJsName((AstType)primitiveExpr.Value, this.Emitter) + "()"); } else { member.Initializer.AcceptVisitor(this.Emitter); } } } } } }
protected virtual void EmitCtorForInstantiableClass() { var typeDef = this.Emitter.GetTypeDefinition(); string name = this.Emitter.Validator.GetCustomTypeName(typeDef, this.Emitter); if (name.IsEmpty()) { name = BridgeTypes.ToTypeScriptName(this.TypeInfo.Type, this.Emitter, false, true); } if (this.TypeInfo.Ctors.Count == 0) { this.Write("new "); this.WriteOpenCloseParentheses(); this.WriteColon(); this.Write(name); this.WriteSemiColon(); this.WriteNewLine(); } else if (this.TypeInfo.Ctors.Count == 1) { var ctor = this.TypeInfo.Ctors.First(); if (!ctor.HasModifier(Modifiers.Public)) { return; } XmlToJsDoc.EmitComment(this, ctor); this.Write("new "); this.EmitMethodParameters(ctor.Parameters, ctor); this.WriteColon(); this.Write(name); this.WriteSemiColon(); this.WriteNewLine(); } else { foreach (var ctor in this.TypeInfo.Ctors) { if (!ctor.HasModifier(Modifiers.Public)) { continue; } if (ctor.Parameters.Count == 0) { XmlToJsDoc.EmitComment(this, ctor); this.Write("new ()"); this.WriteColon(); this.Write(name); this.WriteSemiColon(); this.WriteNewLine(); } XmlToJsDoc.EmitComment(this, ctor); var ctorName = JS.Funcs.CONSTRUCTOR; if (this.TypeInfo.Ctors.Count > 1 && ctor.Parameters.Count > 0) { var overloads = OverloadsCollection.Create(this.Emitter, ctor); ctorName = overloads.GetOverloadName(); } this.Write(ctorName); this.WriteColon(); this.BeginBlock(); this.WriteNew(); this.EmitMethodParameters(ctor.Parameters, ctor); this.WriteColon(); this.Write(name); this.WriteNewLine(); this.EndBlock(); this.WriteSemiColon(); this.WriteNewLine(); } } }
protected void VisitInvocationExpression() { InvocationExpression invocationExpression = this.InvocationExpression; if (this.Emitter.IsForbiddenInvocation(invocationExpression)) { throw new EmitterException(invocationExpression, "This method cannot be invoked directly"); } var oldValue = this.Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling; if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling) { this.WriteAwaiters(invocationExpression); this.Emitter.ReplaceAwaiterByVar = true; this.Emitter.AsyncExpressionHandling = true; } Tuple <bool, bool, string> inlineInfo = this.Emitter.GetInlineCode(invocationExpression); var argsInfo = new ArgumentsInfo(this.Emitter, invocationExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; var argsCount = argsExpressions.Count(); if (inlineInfo != null) { bool isStaticMethod = inlineInfo.Item1; bool isInlineMethod = inlineInfo.Item2; string inlineScript = inlineInfo.Item3; if (isInlineMethod) { if (invocationExpression.Arguments.Count == 1) { var code = invocationExpression.Arguments.First(); var inlineExpression = code as PrimitiveExpression; if (inlineExpression == null) { throw new EmitterException(invocationExpression, "Only primitive expression can be inlined"); } string value = inlineExpression.Value.ToString().Trim(); if (value.Length > 0) { this.Write(inlineExpression.Value); if (value[value.Length - 1] == ';') { this.Emitter.EnableSemicolon = false; this.WriteNewLine(); } } else { // Empty string, emit nothing. this.Emitter.EnableSemicolon = false; } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { MemberReferenceExpression targetMemberRef = invocationExpression.Target as MemberReferenceExpression; bool isBase = targetMemberRef != null && targetMemberRef.Target is BaseReferenceExpression; if (!String.IsNullOrEmpty(inlineScript) && (isBase || invocationExpression.Target is IdentifierExpression)) { argsInfo.ThisArgument = "this"; bool noThis = !inlineScript.Contains("{this}"); if (!isStaticMethod && noThis) { this.WriteThis(); this.WriteDot(); } new InlineArgumentsBlock(this.Emitter, argsInfo, inlineScript).Emit(); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } MemberReferenceExpression targetMember = invocationExpression.Target as MemberReferenceExpression; ResolveResult targetMemberResolveResult = null; if (targetMember != null) { targetMemberResolveResult = this.Emitter.Resolver.ResolveNode(targetMember.Target, this.Emitter); } if (targetMember != null) { var member = this.Emitter.Resolver.ResolveNode(targetMember.Target, this.Emitter); if (member != null && member.Type.Kind == TypeKind.Delegate) { throw new EmitterException(invocationExpression, "Delegate's methods are not supported. Please use direct delegate invoke."); } //var targetResolve = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter); var targetResolve = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter); if (targetResolve != null) { var csharpInvocation = targetResolve as CSharpInvocationResolveResult; InvocationResolveResult invocationResult; bool isExtensionMethodInvocation = false; if (csharpInvocation != null) { if (csharpInvocation.IsExtensionMethodInvocation) { invocationResult = csharpInvocation; isExtensionMethodInvocation = true; var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && resolvedMethod.IsExtensionMethod) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (string.IsNullOrWhiteSpace(inline) && isNative) { invocationResult = null; } } } else { invocationResult = null; } if (this.IsEmptyPartialInvoking(csharpInvocation.Member as IMethod)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null && this.IsEmptyPartialInvoking(invocationResult.Member as IMethod)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } if (invocationResult == null) { invocationResult = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter) as InvocationResolveResult; } if (invocationResult != null) { var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && resolvedMethod.IsExtensionMethod) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (isExtensionMethodInvocation) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else if (!isNative) { string name = BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter) + "." + this.Emitter.GetEntityName(resolvedMethod); var isIgnoreClass = resolvedMethod.DeclaringTypeDefinition != null && this.Emitter.Validator.IsIgnoreType(resolvedMethod.DeclaringTypeDefinition); this.Write(name); if (!isIgnoreClass && argsInfo.HasTypeArguments) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); this.WriteCloseParentheses(); } this.WriteOpenParentheses(); this.WriteThisExtension(invocationExpression.Target); if (argsCount > 0) { this.WriteComma(); } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression).Emit(); this.WriteCloseParentheses(); } if (!string.IsNullOrWhiteSpace(inline) || !isNative) { this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else if (isNative) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { argsExpressions.First().AcceptVisitor(this.Emitter); this.WriteDot(); string name = this.Emitter.GetEntityName(resolvedMethod); this.Write(name); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions.Skip(1), paramsArg, invocationExpression).Emit(); this.WriteCloseParentheses(); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } } } var proto = false; if (targetMember != null && targetMember.Target is BaseReferenceExpression) { var rr = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter) as MemberResolveResult; if (rr != null) { proto = rr.IsVirtualCall; /*var method = rr.Member as IMethod; * if (method != null && method.IsVirtual) * { * proto = true; * } * else * { * var prop = rr.Member as IProperty; * * if (prop != null && prop.IsVirtual) * { * proto = true; * } * }*/ } } if (proto) { var baseType = this.Emitter.GetBaseMethodOwnerTypeDefinition(targetMember.MemberName, targetMember.TypeArguments.Count); var method = invocationExpression.GetParent <MethodDeclaration>(); bool isIgnore = this.Emitter.Validator.IsIgnoreType(baseType); if (isIgnore) { //throw (System.Exception)this.Emitter.CreateException(targetMember.Target, "Cannot call base method, because parent class code is ignored"); } bool needComma = false; var resolveResult = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter); string name = null; if (this.Emitter.TypeInfo.TypeDeclaration.BaseTypes.Any()) { name = BridgeTypes.ToJsName(this.Emitter.TypeInfo.TypeDeclaration.BaseTypes.First(), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } if (resolveResult != null && resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; this.Write(name, ".prototype.", this.Emitter.GetEntityName(invocationResult.Member)); } else { string baseMethod = targetMember.MemberName; this.Write(name, ".prototype.", this.Emitter.AssemblyInfo.PreserveMemberCase ? baseMethod : Object.Net.Utilities.StringUtils.ToLowerCamelCase(baseMethod)); } if (!isIgnore && argsInfo.HasTypeArguments) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); this.WriteCloseParentheses(); } this.WriteDot(); this.Write("call"); this.WriteOpenParentheses(); this.WriteThis(); needComma = true; foreach (var arg in argsExpressions) { if (needComma) { this.WriteComma(); } needComma = true; arg.AcceptVisitor(this.Emitter); } this.WriteCloseParentheses(); } else { var targetResolveResult = this.Emitter.Resolver.ResolveNode(invocationExpression.Target, this.Emitter); var invocationResolveResult = targetResolveResult as MemberResolveResult; IMethod method = null; if (invocationResolveResult != null) { method = invocationResolveResult.Member as IMethod; } if (this.IsEmptyPartialInvoking(method)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } int count = this.Emitter.Writers.Count; invocationExpression.Target.AcceptVisitor(this.Emitter); if (this.Emitter.Writers.Count > count) { var tuple = this.Emitter.Writers.Pop(); if (method != null && method.IsExtensionMethod) { StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; } new InlineArgumentsBlock(this.Emitter, argsInfo, tuple.Item1).Emit(); var result = this.Emitter.Output.ToString(); this.Emitter.Output = tuple.Item2; this.Emitter.IsNewLine = tuple.Item3; this.Write(result); } else { var isIgnore = false; if (method != null && method.DeclaringTypeDefinition != null && this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { isIgnore = true; } if (!isIgnore && argsInfo.HasTypeArguments) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); this.WriteCloseParentheses(); } this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression).Emit(); this.WriteCloseParentheses(); } } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; }
private void EmitExternalBaseCtor(ConstructorDeclaration ctor, ref bool requireNewLine) { if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var inlineCode = this.Emitter.GetInline(member); if (!string.IsNullOrEmpty(inlineCode)) { if (requireNewLine) { this.WriteNewLine(); requireNewLine = false; } this.Write(JS.Types.Bridge.APPLY); this.WriteOpenParentheses(); this.Write("this, "); var argsInfo = new ArgumentsInfo(this.Emitter, ctor.Initializer); new InlineArgumentsBlock(this.Emitter, argsInfo, inlineCode).Emit(); this.WriteCloseParentheses(); this.WriteSemiColon(); this.WriteNewLine(); } else { if (requireNewLine) { this.WriteNewLine(); requireNewLine = false; } var baseType = this.Emitter.GetBaseTypeDefinition(); string name = null; if (this.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } this.Write(name); this.WriteCall(); int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); this.Write("this"); if (ctor.Initializer.Arguments.Count > 0) { this.Write(", "); var argsInfo = new ArgumentsInfo(this.Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } this.WriteCloseParentheses(); this.WriteSemiColon(); this.WriteNewLine(); } } }
protected virtual void EmitMethods(Dictionary <string, List <MethodDeclaration> > methods, Dictionary <string, List <EntityDeclaration> > properties, Dictionary <OperatorType, List <OperatorDeclaration> > operators) { var names = new List <string>(properties.Keys); foreach (var name in names) { var props = properties[name]; foreach (var prop in props) { if (prop is PropertyDeclaration) { this.Emitter.VisitPropertyDeclaration((PropertyDeclaration)prop); } else if (prop is CustomEventDeclaration) { this.Emitter.VisitCustomEventDeclaration((CustomEventDeclaration)prop); } else if (prop is IndexerDeclaration) { this.Emitter.VisitIndexerDeclaration((IndexerDeclaration)prop); } } } if (!this.StaticBlock) { MethodDeclaration entryPoint = null; if (this.TypeInfo.StaticMethods.Any(group => { return(group.Value.Any(method => { var result = Helpers.IsEntryPointMethod(this.Emitter, method); if (result) { entryPoint = method; } return result; })); })) { if (!entryPoint.Body.IsNull) { this.Emitter.VisitMethodDeclaration(entryPoint); } } } names = new List <string>(methods.Keys); foreach (var name in names) { this.EmitMethodsGroup(methods[name]); } if (operators != null) { var ops = new List <OperatorType>(operators.Keys); foreach (var op in ops) { this.EmitOperatorGroup(operators[op]); } } if (this.TypeInfo.ClassType == ClassType.Struct) { if (!this.StaticBlock) { this.EmitStructMethods(); } else { string structName = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); if (this.TypeInfo.Type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(this.TypeInfo.Type, this.Emitter)) { structName = "(" + structName + ")"; } this.EnsureComma(); this.Write(JS.Funcs.GETDEFAULTVALUE + ": function () { return new " + structName + "(); }"); this.Emitter.Comma = true; } } else if (this.StaticBlock) { var ctor = this.TypeInfo.Type.GetConstructors().FirstOrDefault(c => c.Parameters.Count == 0 && this.Emitter.GetInline(c) != null); if (ctor != null) { var code = this.Emitter.GetInline(ctor); this.EnsureComma(); this.Write(JS.Funcs.GETDEFAULTVALUE + ": function () "); this.BeginBlock(); this.Write("return "); var argsInfo = new ArgumentsInfo(this.Emitter, ctor); new InlineArgumentsBlock(this.Emitter, argsInfo, code).Emit(); this.Write(";"); this.WriteNewLine(); this.EndBlock(); this.Emitter.Comma = true; } } }
protected virtual void EmitStructMethods() { var typeDef = this.Emitter.GetTypeDefinition(); string structName = this.Emitter.Validator.GetCustomTypeName(typeDef, this.Emitter); if (structName.IsEmpty()) { structName = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); } var fields = this.TypeInfo.InstanceConfig.Fields; var props = this.TypeInfo.InstanceConfig.Properties.Where(ent => { var p = ent.Entity as PropertyDeclaration; return(p != null && p.Getter != null && p.Getter.Body.IsNull && p.Setter != null && p.Setter.Body.IsNull); }); var list = fields.ToList(); list.AddRange(props); if (list.Count == 0) { string name = "clone".Ident(); TransformCtx.CurClassMethodNames.Add(new TransformCtx.MethodInfo() { Name = name }); //this.EnsureComma(); this.EnsureNewLine(); this.Write(name, " = function(this, to) return this end"); this.Emitter.Comma = true; return; } const string kGetHashCode = "GetHashCode"; if (!this.TypeInfo.InstanceMethods.ContainsKey(kGetHashCode)) { TransformCtx.CurClassMethodNames.Add(new TransformCtx.MethodInfo() { Name = kGetHashCode }); //this.EnsureComma(); this.EnsureNewLine(); this.Write(kGetHashCode, " = function(this) "); this.BeginFunctionBlock(); this.Write("local hash = 17"); foreach (var field in list) { string fieldName = field.GetName(this.Emitter); this.WriteNewLine(); this.Write("hash = hash * 23 + "); this.Write("(this." + fieldName); this.Write(" == nil and 0 or "); this.Write("System.Object.", kGetHashCode, "("); this.Write("this." + fieldName); this.Write("))"); } this.WriteNewLine(); this.Write("return hash"); this.WriteNewLine(); this.EndFunctionBlock(); this.Emitter.Comma = true; } const string kEqualsObj = "EqualsObj"; if (!this.TypeInfo.InstanceMethods.ContainsKey("Equals")) { TransformCtx.CurClassMethodNames.Add(new TransformCtx.MethodInfo() { Name = kEqualsObj }); //this.EnsureComma(); this.EnsureNewLine(); this.Write(kEqualsObj, " = function (this, o) "); this.BeginFunctionBlock(); this.Write("if getmetatable(o) ~= "); this.Write(structName); this.Write(" then"); this.BeginFunctionBlock(); this.Write("return false"); this.WriteNewLine(); this.EndFunctionBlock(); this.WriteNewLine(); this.Write("return "); bool and = false; bool isIndent = false; foreach (var field in list) { string fieldName = field.GetName(this.Emitter); if (and) { if (!isIndent) { this.Indent(); isIndent = true; } this.WriteNewLine(); this.Write("and "); } else { and = true; } this.Write("System.Object.equalsStatic(this."); this.Write(fieldName); this.Write(", o."); this.Write(fieldName); this.Write(")"); } if (isIndent) { this.Outdent(); } this.WriteNewLine(); this.EndFunctionBlock(); this.Emitter.Comma = true; } TransformCtx.CurClassMethodNames.Add(new TransformCtx.MethodInfo() { Name = "clone".Ident() }); //this.EnsureComma(); this.EnsureNewLine(); this.Write("clone".Ident(), " = function (this, to) "); this.BeginFunctionBlock(); this.Write("local s = to or "); this.Write(structName); this.Write(CtorOpenCloseParentheses); foreach (var field in list) { this.WriteNewLine(); string fieldName = field.GetName(this.Emitter); this.Write("s."); this.Write(fieldName); this.Write(" = this."); this.Write(fieldName); } this.WriteNewLine(); this.Write("return s"); this.WriteNewLine(); this.EndFunctionBlock(); this.Emitter.Comma = true; }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; ResolveResult resolveResult = null; resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id)) { if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(id) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[id]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this); return; } if (resolveResult is TypeResolveResult) { if (this.Emitter.Validator.IsIgnoreType(resolveResult.Type.GetDefinition())) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); } else { this.Write("Bridge.get(" + BridgeTypes.ToJsName(resolveResult.Type, this.Emitter) + ")"); } return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { if (!this.Emitter.Validator.IsIgnoreType(memberResult.Member.DeclaringTypeDefinition)) { this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); } else { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); } } else { this.WriteThis(); } inlineCode = inlineCode.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } return; } if (hasInline && memberResult.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } string appendAdditionalCode = null; if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)memberResult.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (Helpers.IsFieldProperty(memberResult.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); } else { trg = "this"; } this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), "()", "{0})")); } else { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is DefaultResolvedEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write( OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member, true)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is TypeResolveResult) { var typeResolveResult = (TypeResolveResult)resolveResult; var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition()); if (!isNative) { this.Write("Bridge.get(" + BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); } else { this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); } if (typeResolveResult.Type.TypeParameterCount > 0) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, this.IdentifierExpression.TypeArguments).Emit(); this.WriteCloseParentheses(); } if (!isNative) { this.Write(")"); } } else if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName()); } else { this.Write(resolveResult.ToString()); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this); } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { bool addClose = false; string leftInterfaceTempVar = null; if (orr.OperatorType == ExpressionType.OrElse || orr.OperatorType == ExpressionType.AndAlso) { var orElse = orr.OperatorType == ExpressionType.OrElse; var left = orr.Operands[0]; var memberTargetrr = left as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(left is ThisResolveResult || left is TypeResolveResult || left is LocalResolveResult || left is ConstantResolveResult || isField)) { this.WriteOpenParentheses(); leftInterfaceTempVar = this.GetTempVarName(); this.Write(leftInterfaceTempVar); this.Write(" = "); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.WriteComma(); addClose = true; } var m = FindOperatorTrueOrFalse(left.Type, orElse); this.Write(BridgeTypes.ToJsName(m.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, m).GetOverloadName()); this.WriteOpenParentheses(); if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.WriteCloseParentheses(); this.Write(" ? "); if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.Write(" : "); } if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT; switch (this.BinaryOperatorExpression.Operator) { case BinaryOperatorType.GreaterThan: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.GreaterThanOrEqual: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.Equality: action = JS.Funcs.Math.LIFTEQ; break; case BinaryOperatorType.InEquality: action = JS.Funcs.Math.LIFTNE; break; case BinaryOperatorType.LessThan: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.LessThanOrEqual: action = JS.Funcs.Math.LIFTCMP; break; } this.Write(action + "("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); this.Write(", "); binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); } else { new ExpressionListBlock(this.Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null, null, 0).Emit(); } this.WriteCloseParentheses(); if (addClose) { this.WriteCloseParentheses(); } return(true); } } return(false); }
protected virtual void EmitClassHeader() { TypeDefinition baseType = this.Emitter.GetBaseTypeDefinition(); var typeDef = this.Emitter.GetTypeDefinition(); string name = this.Emitter.Validator.GetCustomTypeName(typeDef); this.IsGeneric = typeDef.GenericParameters.Count > 0; if (name.IsEmpty()) { name = BridgeTypes.DefinitionToJsName(this.TypeInfo.Type, this.Emitter); } this.Write(Bridge.Translator.Emitter.ROOT + ".define"); this.WriteOpenParentheses(); this.Write("'" + name, "'"); this.StartPosition = this.Emitter.Output.Length; this.Write(", "); if (this.IsGeneric) { this.WriteFunction(); this.WriteOpenParentheses(); foreach (var p in typeDef.GenericParameters) { this.EnsureComma(false); this.Write(p.Name); this.Emitter.Comma = true; } this.Emitter.Comma = false; this.WriteCloseParentheses(); this.Write(" { return "); } this.BeginBlock(); string extend = this.Emitter.GetTypeHierarchy(); if (extend.IsNotEmpty() && !this.TypeInfo.IsEnum) { var bridgeType = this.Emitter.BridgeTypes.Get(this.Emitter.TypeInfo); if (this.TypeInfo.InstanceMethods.Any(m => m.Value.Any(subm => this.Emitter.GetEntityName(subm) == "inherits")) || this.TypeInfo.InstanceConfig.Fields.Any(m => m.GetName(this.Emitter) == "inherits")) { this.Write("$"); } this.Write("inherits"); this.WriteColon(); if (Helpers.IsTypeArgInSubclass(bridgeType.TypeDefinition, bridgeType.TypeDefinition, this.Emitter, false)) { this.WriteFunction(); this.WriteOpenCloseParentheses(true); this.WriteOpenBrace(true); this.WriteReturn(true); this.Write(extend); this.WriteSemiColon(); this.WriteCloseBrace(true); } else { this.Write(extend); } this.Emitter.Comma = true; } if (this.TypeInfo.Module != null) { this.WriteScope(); } }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable."); string action = "lift"; switch (this.BinaryOperatorExpression.Operator) { case BinaryOperatorType.GreaterThan: action = "liftcmp"; break; case BinaryOperatorType.GreaterThanOrEqual: action = "liftcmp"; break; case BinaryOperatorType.Equality: action = "lifteq"; break; case BinaryOperatorType.InEquality: action = "liftne"; break; case BinaryOperatorType.LessThan: action = "liftcmp"; break; case BinaryOperatorType.LessThanOrEqual: action = "liftcmp"; break; } this.Write(action + "("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null).Emit(); this.WriteCloseParentheses(); return(true); } } return(false); }
public virtual void ConvertParamsToReferences(IEnumerable <ParameterDeclaration> declarations) { if (declarations.Any()) { var p = declarations.First().Parent; if (p != null) { var rr = this.Emitter.Resolver.ResolveNode(p, this.Emitter) as MemberResolveResult; if (rr != null) { var method = rr.Member as DefaultResolvedMethod; if (method != null) { var expandParams = method.Attributes.Any(a => a.AttributeType.FullName == "Bridge.ExpandParamsAttribute"); foreach (var prm in method.Parameters) { if (prm.IsOptional) { var name = prm.Name; if (Helpers.IsReservedWord(this.Emitter, name)) { name = Helpers.ChangeReservedWord(name); } this.Write(string.Format("if ({0} === void 0) {{ {0} = ", name)); if (prm.ConstantValue == null && prm.Type.Kind == TypeKind.Struct && !prm.Type.IsKnownType(KnownTypeCode.NullableOfT)) { this.Write(Inspector.GetStructDefaultValue(prm.Type, this.Emitter)); } else if (prm.ConstantValue == null && prm.Type.Kind == TypeKind.TypeParameter) { this.Write(JS.Funcs.BRIDGE_GETDEFAULTVALUE + "(" + BridgeTypes.ToJsName(prm.Type, this.Emitter) + ")"); } else if (prm.Type.Kind == TypeKind.Enum) { var enumMode = Helpers.EnumEmitMode(prm.Type); if (enumMode >= 3 && enumMode < 7) { var members = prm.Type.GetMembers(options: GetMemberOptions.IgnoreInheritedMembers); var member = members.FirstOrDefault(m => m is IField field && field.ConstantValue == prm.ConstantValue); if (member != null) { string enumStringName = this.Emitter.GetEntityName(member); this.WriteScript(enumStringName); } else { this.WriteScript(prm.ConstantValue); } } else { this.WriteScript(prm.ConstantValue); } } else { this.WriteScript(prm.ConstantValue); } this.Write("; }"); this.WriteNewLine(); } else if (prm.IsParams) { var name = prm.Name; if (Helpers.IsReservedWord(this.Emitter, name)) { name = Helpers.ChangeReservedWord(name); } if (expandParams) { this.Write(string.Format("{0} = " + JS.Types.ARRAY + "." + JS.Fields.PROTOTYPE + "." + JS.Funcs.SLICE + "." + JS.Funcs.CALL + "(" + JS.Vars.ARGUMENTS + ", {1});", name, method.Parameters.IndexOf(prm) + method.TypeParameters.Count)); } else { this.Write(string.Format("if ({0} === void 0) {{ {0} = []; }}", name)); } this.WriteNewLine(); } } } } } } declarations.ToList().ForEach(item => { var lrr = item.Parent != null ? (LocalResolveResult)this.Emitter.Resolver.ResolveNode(item, this.Emitter) : null; var isReferenceLocal = lrr != null && this.Emitter.LocalsMap.ContainsKey(lrr.Variable) && this.Emitter.LocalsMap[lrr.Variable].EndsWith(".v"); if (item.Parent == null && item.Name == "value") { var p = this.Emitter.LocalsMap.FirstOrDefault(pair => pair.Key.Name == "value"); if (p.Value != null && p.Value.EndsWith(".v")) { isReferenceLocal = true; } } if (isReferenceLocal && !(item.ParameterModifier == ParameterModifier.Out || item.ParameterModifier == ParameterModifier.Ref)) { this.Write(string.Format("{0} = {{v:{0}}};", this.Emitter.LocalsNamesMap[item.Name])); this.WriteNewLine(); } }); }
private void HandleDecimal(ResolveResult resolveOperator, bool isLong = false) { var orr = resolveOperator as OperatorResolveResult; var op = this.UnaryOperatorExpression.Operator; var oldType = this.Emitter.UnaryOperatorType; var oldAccessor = this.Emitter.IsUnaryAccessor; var typeCode = isLong ? KnownTypeCode.Int64 : KnownTypeCode.Decimal; this.Emitter.UnaryOperatorType = op; var argResolverResult = this.Emitter.Resolver.ResolveNode(this.UnaryOperatorExpression.Expression, this.Emitter); bool nullable = NullableType.IsNullable(argResolverResult.Type); bool isAccessor = false; var memberArgResolverResult = argResolverResult as MemberResolveResult; if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty) { var isIgnore = this.Emitter.Validator.IsExternalType(memberArgResolverResult.Member.DeclaringTypeDefinition); var inlineAttr = this.Emitter.GetAttribute(memberArgResolverResult.Member.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute"); var ignoreAccessor = this.Emitter.Validator.IsExternalType(((IProperty)memberArgResolverResult.Member).Getter); var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member); isAccessor = ((IProperty)memberArgResolverResult.Member).IsIndexer; if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer) { isAccessor = false; } } else if (argResolverResult is ArrayAccessResolveResult) { isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1; } var isOneOp = op == UnaryOperatorType.Increment || op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostIncrement || op == UnaryOperatorType.PostDecrement; if (isAccessor && isOneOp) { this.Emitter.IsUnaryAccessor = true; if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.Emitter.IsUnaryAccessor = false; this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.Emitter.IsUnaryAccessor = true; this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } this.Emitter.UnaryOperatorType = oldType; this.Emitter.IsUnaryAccessor = oldAccessor; return; } var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (orr != null && method == null) { var name = Helpers.GetUnaryOperatorMethodName(this.UnaryOperatorExpression.Operator); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (orr != null && orr.IsLiftedOperator) { if (!isOneOp) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); } string action = JS.Funcs.Math.LIFT1; string op_name = null; switch (this.UnaryOperatorExpression.Operator) { case UnaryOperatorType.Minus: op_name = JS.Funcs.Math.NEG; break; case UnaryOperatorType.Plus: op_name = "clone"; break; case UnaryOperatorType.BitNot: op_name = "not"; break; case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "(\"" + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "\", "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true); this.Write(")"); this.WriteCloseParentheses(); this.Write(" : null"); break; case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "(\"" + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "\", "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true); this.Write(")"); this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); this.Write(" : null"); break; } if (!isOneOp) { this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit(); this.AddOveflowFlag(typeCode, op_name, true); this.WriteCloseParentheses(); } } else if (method == null) { string op_name = null; var isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement; if (isStatement) { if (op == UnaryOperatorType.PostIncrement) { op = UnaryOperatorType.Increment; } else if (op == UnaryOperatorType.PostDecrement) { op = UnaryOperatorType.Decrement; } } switch (op) { case UnaryOperatorType.Minus: op_name = JS.Funcs.Math.NEG; break; case UnaryOperatorType.Plus: op_name = "clone"; break; case UnaryOperatorType.BitNot: op_name = "not"; break; case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: if (!isStatement) { this.WriteOpenParentheses(); } this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("." + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "("); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false); this.Write(")"); if (!isStatement) { this.WriteCloseParentheses(); } break; case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("." + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "("); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false); this.Write("), "); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); break; } if (!isOneOp) { this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.AddOveflowFlag(typeCode, op_name, false); this.WriteCloseParentheses(); } } else { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { if (isOneOp) { var isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement; if (isStatement || this.UnaryOperatorExpression.Operator == UnaryOperatorType.Increment || this.UnaryOperatorExpression.Operator == UnaryOperatorType.Decrement) { if (!isStatement) { this.WriteOpenParentheses(); } this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit (); if (!isStatement) { this.WriteCloseParentheses(); } } else { this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit(); this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); } } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit(); } } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit(); this.WriteCloseParentheses(); } } this.Emitter.UnaryOperatorType = oldType; }
protected void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { var typeDef = this.Emitter.GetTypeDefinition(); var overloads = OverloadsCollection.Create(this.Emitter, methodDeclaration); if (overloads.HasOverloads) { string name = overloads.GetOverloadName(); this.Write(name); } else { this.Write(this.Emitter.GetEntityName(methodDeclaration)); } var isGeneric = methodDeclaration.TypeParameters.Count > 0; if (isGeneric) { bool needComma = false; this.Write("<"); foreach (var p in methodDeclaration.TypeParameters) { if (needComma) { this.WriteComma(); } needComma = true; this.Write(p.Name); } this.Write(">"); this.WriteOpenParentheses(); var comma = false; foreach (var p in methodDeclaration.TypeParameters) { if (comma) { this.WriteComma(); } this.Write(p.Name); this.WriteColon(); this.WriteOpenBrace(); this.Write("prototype"); this.WriteColon(); this.Write(p.Name); this.WriteCloseBrace(); comma = true; } this.WriteCloseParentheses(); this.WriteColon(); this.WriteOpenBrace(); this.WriteSpace(); } this.EmitMethodParameters(methodDeclaration.Parameters, methodDeclaration); this.WriteColon(); var retType = BridgeTypes.ToJsName(methodDeclaration.ReturnType, this.Emitter); retType = EmitBlock.HandleType(retType); this.Write(retType); if (isGeneric) { this.WriteSpace(); this.WriteCloseBrace(); } this.WriteSemiColon(); this.WriteNewLine(); }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; int pos = this.Emitter.Output.Length; bool isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; bool isConstTarget = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (targetrr is ConstantResolveResult) { isConstTarget = true; } var memberTargetrr = targetrr as MemberResolveResult; if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && Helpers.EnumEmitMode(memberTargetrr.Type) == 2) { isConstTarget = true; } if (memberReferenceExpression.Target is ParenthesizedExpression || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Int64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.UInt64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Decimal))) { isConstTarget = false; } var isInvoke = memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression); if (isInvoke) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } else if (expressionResolveResult is MemberResolveResult) { if (((MemberResolveResult)expressionResolveResult).Member is IProperty) { resolveResult = expressionResolveResult; } } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } bool isDynamic = false; if (resolveResult is DynamicInvocationResolveResult) { var dynamicResolveResult = (DynamicInvocationResolveResult)resolveResult; var group = dynamicResolveResult.Target as MethodGroupResolveResult; if (group != null && group.Methods.Count() > 1) { var method = group.Methods.FirstOrDefault(m => { if (dynamicResolveResult.Arguments.Count != m.Parameters.Count) { return(false); } for (int i = 0; i < m.Parameters.Count; i++) { var argType = dynamicResolveResult.Arguments[i].Type; if (argType.Kind == TypeKind.Dynamic) { argType = this.Emitter.Resolver.Compilation.FindType(TypeCode.Object); } if (!m.Parameters[i].Type.Equals(argType)) { return(false); } } return(true); }) ?? group.Methods.Last(); isDynamic = true; resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); resolveResult = new InvocationResolveResult(resolveResult, method, dynamicResolveResult.Arguments); } } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; var globalTarget = member != null?this.Emitter.IsGlobalTarget(member.Member) : null; if (member != null && member.Member.Attributes.Any(a => a.AttributeType.FullName == "Bridge.NonScriptableAttribute")) { throw new EmitterException(this.MemberReferenceExpression, "Member " + member.ToString() + " is marked as not usable from script"); } if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { var interceptor = this.Emitter.Plugins.OnReference(this, this.MemberReferenceExpression, member); if (interceptor.Cancel) { return; } if (!string.IsNullOrEmpty(interceptor.Replacement)) { this.Write(interceptor.Replacement); return; } } if (globalTarget != null && globalTarget.Item1) { var target = globalTarget.Item2; if (!string.IsNullOrWhiteSpace(target)) { bool assign = false; var memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent; var targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression; var assignment = memberExpression as AssignmentExpression; if (assignment != null && assignment.Right == targetExpression) { assign = true; } else { var varInit = memberExpression as VariableInitializer; if (varInit != null && varInit.Initializer == targetExpression) { assign = true; } else if (memberExpression is InvocationExpression) { var targetInvocation = (InvocationExpression)memberExpression; if (targetInvocation.Arguments.Any(a => a == targetExpression)) { assign = true; } } } if (assign) { if (resolveResult is InvocationResolveResult) { this.PushWriter(target); } else { this.Write(target); } return; } } if (resolveResult is InvocationResolveResult) { this.PushWriter(""); } return; } Tuple <bool, bool, string> inlineInfo = member != null ? (isDynamic ? ((Emitter)this.Emitter).GetInlineCodeFromMember(member.Member, null) : this.Emitter.GetInlineCode(memberReferenceExpression)) : null; //string inline = member != null ? this.Emitter.GetInline(member.Member) : null; string inline = inlineInfo != null ? inlineInfo.Item3 : null; if (string.IsNullOrEmpty(inline) && member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var parentInvocation = memberReferenceExpression.Parent as InvocationExpression; if (parentInvocation == null || parentInvocation.Target != memberReferenceExpression) { var method = (IMethod)member.Member; if (method.TypeArguments.Count > 0 || method.IsExtensionMethod) { inline = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } } if (member != null && member.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(member.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inline = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && Helpers.HasThis(inline); inline = hasInline ? Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline; bool isInterfaceMember = false; if (hasInline && inline.StartsWith("<self>")) { hasThis = true; inline = inline.Substring(6); } bool nativeImplementation = true; bool isInterface = inline == null && member != null && member.Member.DeclaringTypeDefinition != null && member.Member.DeclaringTypeDefinition.Kind == TypeKind.Interface; var hasTypeParemeter = isInterface && Helpers.IsTypeParameterType(member.Member.DeclaringType); if (isInterface) { var itypeDef = member.Member.DeclaringTypeDefinition; var variance = MetadataUtils.IsJsGeneric(itypeDef, this.Emitter) && itypeDef.TypeParameters != null && itypeDef.TypeParameters.Any(typeParameter => typeParameter.Variance != VarianceModifier.Invariant); if (variance) { isInterfaceMember = true; } else { var ei = this.Emitter.Validator.IsExternalInterface(itypeDef); if (ei != null) { nativeImplementation = ei.IsNativeImplementation; } else { nativeImplementation = member.Member.DeclaringTypeDefinition.ParentAssembly.AssemblyName == CS.NS.BRIDGE || !this.Emitter.Validator.IsExternalType(member.Member.DeclaringTypeDefinition); } if (ei != null && ei.IsSimpleImplementation) { nativeImplementation = false; isInterfaceMember = false; } else if (ei != null || hasTypeParemeter) { if (hasTypeParemeter || !nativeImplementation) { isInterfaceMember = true; } } } } string interfaceTempVar = null; if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; var oldInline = inline; string thisArg = null; bool isSimple = true; if (this.MemberReferenceExpression.Target is BaseReferenceExpression) { thisArg = "this"; } else { this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } this.WriteSimpleTarget(resolveResult); if (isConstTarget) { this.Write(")"); } thisArg = this.Emitter.Output.ToString(); if (Regex.Matches(inline, @"\{(\*?)this\}").Count > 1) { var mrr = resolveResult as MemberResolveResult; bool isField = mrr != null && mrr.Member is IField && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is LocalResolveResult || mrr.TargetResult is MemberResolveResult && ((MemberResolveResult)mrr.TargetResult).Member is IField); isSimple = (mrr != null && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is ConstantResolveResult || mrr.TargetResult is LocalResolveResult)) || isField; } } int thisIndex; inline = member != null?Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline; if (!isSimple) { StringBuilder sb = new StringBuilder(); sb.Append("("); var tempVar = this.GetTempVarName(); inline = inline.Replace("{this}", tempVar); thisIndex = tempVar.Length + 2; sb.Append(tempVar); sb.Append(" = "); sb.Append(thisArg); sb.Append(", "); sb.Append(inline); sb.Append(")"); inline = sb.ToString(); } else { thisIndex = inline.IndexOf("{this}", StringComparison.Ordinal); inline = inline.Replace("{this}", thisArg); } if (member != null && member.Member is IProperty) { this.Emitter.Output = new StringBuilder(); inline = inline.Replace("{0}", "[[0]]"); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); inline = this.Emitter.Output.ToString(); inline = inline.Replace("[[0]]", "{0}"); } else if (member != null && member.Member is IEvent) { this.Emitter.Output = new StringBuilder(); inline = inline.Replace("{0}", "[[0]]"); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); inline = this.Emitter.Output.ToString(); inline = inline.Replace("[[0]]", "{0}"); } this.Emitter.Output = new StringBuilder(inline); Helpers.CheckValueTypeClone(resolveResult, this.MemberReferenceExpression, this, pos); inline = this.Emitter.Output.ToString(); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inline, null, thisArg, range); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), oldInline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (member != null && member.Member is IField && inline.Contains("{0}")) { this.PushWriter(inline, null, thisArg, range); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inline)) { this.PushWriter(inline, null, thisArg, range); } else { this.Write(inline); } } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member)) { var parentExpression = memberReferenceExpression.Parent as MemberReferenceExpression; bool wrap = false; if (parentExpression != null) { var ii = this.Emitter.GetInlineCode(parentExpression); if (string.IsNullOrEmpty(ii.Item3)) { wrap = true; this.WriteOpenParentheses(); } } this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); if (wrap) { this.WriteCloseParentheses(); } } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as ITypeDefinition; if (typeDef != null) { var enumMode = Helpers.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsExternalType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3 && enumMode < 7) { string enumStringName = this.Emitter.GetEntityName(member.Member); this.WriteScript(enumStringName); return; } } } if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); return; } else { if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var parentInvocation = memberReferenceExpression.Parent as InvocationExpression; if (parentInvocation == null || parentInvocation.Target != memberReferenceExpression) { if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_CACHE_BIND); this.WriteOpenParentheses(); if (memberReferenceExpression.Target is BaseReferenceExpression) { this.WriteThis(); } else { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, false); } this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (interfaceTempVar != null) { this.Write(interfaceTempVar); } else { this.WriteSimpleTarget(resolveResult); } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar, member, false); } else { this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation)); } if (!isStatic) { this.Write(")"); } } return; } } bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } } if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (targetVar == null && isInterfaceMember) { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, true); } else { this.WriteSimpleTarget(resolveResult); } if (member != null && targetrr != null && targetrr.Type.Kind == TypeKind.Delegate && (member.Member.Name == "Invoke")) { var method = member.Member as IMethod; if (!(method != null && method.IsExtensionMethod)) { return; } } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } } var targetResolveResult = targetrr as MemberResolveResult; if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null) { if (isRefArg) { this.WriteComma(); } else if (!isInterfaceMember && !this.NoTarget) { this.WriteDot(); } } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment) || (member.Member != null && member.Member is IEvent)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || (!this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition) || member.Member.IsStatic))) { if (member.Member is IProperty && targetrr != null && targetrr.Type.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(targetrr.Type.GetDefinition()) && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { this.Write(this.Emitter.GetLiteralEntityName(member.Member)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var name = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); var property = (IProperty)member.Member; var proto = member.IsVirtualCall || property.IsVirtual || property.IsOverride; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && !property.IsIndexer && proto) { var alias = BridgeTypes.ToJsName(member.Member.DeclaringType, this.Emitter, isAlias: true); if (alias.StartsWith("\"")) { alias = alias.Insert(1, "$"); name = alias + "+\"$" + name + "\""; this.WriteIdentifier(name, false); } else { name = "$" + alias + "$" + name; this.WriteIdentifier(name); } } else { this.WriteIdentifier(name); } } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var fieldName = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); if (isRefArg) { this.WriteScript(fieldName); } else { this.WriteIdentifier(fieldName); } } } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = resolveResult as CSharpInvocationResolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName(!nativeImplementation)); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(!nativeImplementation)); } } else if (member.Member is IEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract, Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); } else { this.Write(Helpers.GetEventRef(member.Member, this.Emitter, this.Emitter.AssignmentType != AssignmentOperatorType.Add, ignoreInterface: !nativeImplementation)); } this.WriteOpenParentheses(); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { this.Write(this.Emitter.GetEntityName(member.Member)); } } } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var memberName = this.Emitter.GetEntityName(member.Member); if (isRefArg) { this.WriteScript(memberName); } else { this.WriteIdentifier(memberName); } } } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
private void HandleType(ResolveResult resolveOperator, KnownTypeCode typeCode, string op_name, string action) { var orr = resolveOperator as OperatorResolveResult; var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(this.BinaryOperatorExpression.Operator); var type = this.Emitter.Resolver.Compilation.FindType(typeCode); method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = this.Emitter.GetInline(method); if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.BinaryOperatorExpression.Left, this.BinaryOperatorExpression.Right }, null, null, 0) .Emit(); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.BinaryOperatorExpression, orr, method), inline).Emit(); } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, new Expression[] { this.BinaryOperatorExpression.Left, this.BinaryOperatorExpression.Right }, null, null, 0) .Emit(); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } } else { if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.BinaryOperatorExpression.Left, this.BinaryOperatorExpression.Right }, null, null, 0) .Emit(); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else { this.BinaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.BinaryOperatorExpression.Right.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } } }
protected virtual void EmitStructMethods() { var typeDef = this.Emitter.GetTypeDefinition(); string structName = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); bool immutable = this.Emitter.Validator.IsImmutableType(typeDef); if (!immutable) { var mutableFields = this.TypeInfo.Type.GetFields(f => !f.IsReadOnly && !f.IsConst, GetMemberOptions.IgnoreInheritedMembers); var autoProps = typeDef.Properties.Where(Helpers.IsAutoProperty); var autoEvents = this.TypeInfo.Type.GetEvents(null, GetMemberOptions.IgnoreInheritedMembers); immutable = !mutableFields.Any() && !autoProps.Any() && !autoEvents.Any(); } var fields = this.TypeInfo.InstanceConfig.Fields; var props = this.TypeInfo.InstanceConfig.Properties.Where(ent => { var p = ent.Entity as PropertyDeclaration; return(p != null && p.Getter != null && p.Getter.Body.IsNull && p.Setter != null && p.Setter.Body.IsNull); }); var list = fields.ToList(); list.AddRange(props); if (list.Count == 0) { this.EnsureComma(); this.Write(JS.Funcs.CLONE + ": function (to) { return this; }"); this.Emitter.Comma = true; return; } if (!this.TypeInfo.InstanceMethods.ContainsKey(CS.Methods.GETHASHCODE)) { this.EnsureComma(); this.Write(JS.Funcs.GETHASHCODE + ": function () "); this.BeginBlock(); this.Write("var hash = 17;"); this.WriteNewLine(); var nameHashValue = new HashHelper().GetDeterministicHash(this.TypeInfo.Name); this.Write("hash = hash * 23" + nameHashValue + ";"); foreach (var field in list) { string fieldName = field.GetName(this.Emitter); this.WriteNewLine(); this.Write("hash = hash * 23 + "); this.Write("(this." + fieldName); this.Write(" == null ? 0 : "); this.Write(JS.Funcs.BRIDGE_GETHASHCODE + "("); this.Write("this." + fieldName); this.Write("));"); } this.WriteNewLine(); this.Write("return hash;"); this.WriteNewLine(); this.EndBlock(); this.Emitter.Comma = true; } if (!this.TypeInfo.InstanceMethods.ContainsKey(CS.Methods.EQUALS)) { this.EnsureComma(); this.Write(JS.Funcs.EQUALS + ": function (o) "); this.BeginBlock(); this.Write("if (!" + JS.Funcs.BRIDGE_IS + "(o, "); this.Write(structName); this.Write(")) "); this.BeginBlock(); this.Write("return false;"); this.WriteNewLine(); this.EndBlock(); this.WriteNewLine(); this.Write("return "); bool and = false; foreach (var field in list) { string fieldName = field.GetName(this.Emitter); if (and) { this.Write(" && "); } and = true; this.Write(JS.Funcs.BRIDGE_EQUALS + "(this."); this.Write(fieldName); this.Write(", o."); this.Write(fieldName); this.Write(")"); } this.Write(";"); this.WriteNewLine(); this.EndBlock(); this.Emitter.Comma = true; } this.EnsureComma(); if (immutable) { this.Write(JS.Funcs.CLONE + ": function (to) { return this; }"); } else { this.Write(JS.Funcs.CLONE + ": function (to) "); this.BeginBlock(); this.Write("var s = to || new "); if (this.TypeInfo.Type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(this.TypeInfo.Type, this.Emitter)) { structName = "(" + structName + ")"; } this.Write(structName); this.Write("();"); foreach (var field in list) { this.WriteNewLine(); string fieldName = field.GetName(this.Emitter); this.Write("s."); this.Write(fieldName); this.Write(" = "); int insertPosition = this.Emitter.Output.Length; this.Write("this."); this.Write(fieldName); var rr = this.Emitter.Resolver.ResolveNode(field.Entity, this.Emitter) as MemberResolveResult; if (rr == null && field.VarInitializer != null) { rr = Emitter.Resolver.ResolveNode(field.VarInitializer, Emitter) as MemberResolveResult; } if (rr != null) { Helpers.CheckValueTypeClone(rr, null, this, insertPosition); } this.Write(";"); } this.WriteNewLine(); this.Write("return s;"); this.WriteNewLine(); this.EndBlock(); } this.Emitter.Comma = true; }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, out isCastAttr); var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = this.Emitter.Validator.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter))) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } if (method == CS.Ops.CAST) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write("Bridge.is("); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
protected void VisitInvocationExpression() { InvocationExpression invocationExpression = this.InvocationExpression; int pos = this.Emitter.Output.Length; if (this.Emitter.IsForbiddenInvocation(invocationExpression)) { throw new EmitterException(invocationExpression, "This method cannot be invoked directly"); } var oldValue = this.Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling; if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling) { this.WriteAwaiters(invocationExpression); this.Emitter.ReplaceAwaiterByVar = true; this.Emitter.AsyncExpressionHandling = true; } Tuple <bool, bool, string> inlineInfo = this.Emitter.GetInlineCode(invocationExpression); var argsInfo = new ArgumentsInfo(this.Emitter, invocationExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; var targetResolve = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter); var csharpInvocation = targetResolve as CSharpInvocationResolveResult; MemberReferenceExpression targetMember = invocationExpression.Target as MemberReferenceExpression; bool isObjectLiteral = csharpInvocation != null && csharpInvocation.Member.DeclaringTypeDefinition != null?this.Emitter.Validator.IsObjectLiteral(csharpInvocation.Member.DeclaringTypeDefinition) : false; var interceptor = this.Emitter.Plugins.OnInvocation(this, this.InvocationExpression, targetResolve as InvocationResolveResult); if (interceptor.Cancel) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } if (!string.IsNullOrEmpty(interceptor.Replacement)) { this.Write(interceptor.Replacement); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } if (inlineInfo != null) { bool isStaticMethod = inlineInfo.Item1; bool isInlineMethod = inlineInfo.Item2; string inlineScript = inlineInfo.Item3; if (isInlineMethod) { if (invocationExpression.Arguments.Count > 0) { var code = invocationExpression.Arguments.First(); var inlineExpression = code as PrimitiveExpression; if (inlineExpression == null) { throw new EmitterException(invocationExpression, "Only primitive expression can be inlined"); } string value = inlineExpression.Value.ToString().Trim(); if (value.Length > 0) { value = InlineArgumentsBlock.ReplaceInlineArgs(this, inlineExpression.Value.ToString(), invocationExpression.Arguments.Skip(1).ToArray()); this.Write(value); value = value.Trim(); if (value[value.Length - 1] == ';' || value.EndsWith("*/", StringComparison.InvariantCulture) || value.StartsWith("//")) { this.Emitter.EnableSemicolon = false; this.WriteNewLine(); } } else { // Empty string, emit nothing. this.Emitter.EnableSemicolon = false; } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { MemberReferenceExpression targetMemberRef = invocationExpression.Target as MemberReferenceExpression; bool isBase = targetMemberRef != null && targetMemberRef.Target is BaseReferenceExpression; if (!String.IsNullOrEmpty(inlineScript) && (isBase || invocationExpression.Target is IdentifierExpression)) { argsInfo.ThisArgument = "this"; bool noThis = !inlineScript.Contains("{this}"); if (inlineScript.StartsWith("<self>")) { noThis = false; inlineScript = inlineScript.Substring(6); } if (!noThis) { Emitter.ThisRefCounter++; } if (!isStaticMethod && noThis) { this.WriteThis(); this.WriteDot(); } new InlineArgumentsBlock(this.Emitter, argsInfo, inlineScript).Emit(); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } if (targetMember != null || isObjectLiteral) { var member = targetMember != null?this.Emitter.Resolver.ResolveNode(targetMember.Target, this.Emitter) : null; if (targetResolve != null) { InvocationResolveResult invocationResult; bool isExtensionMethodInvocation = false; if (csharpInvocation != null) { if (member != null && member.Type.Kind == TypeKind.Delegate && (/*csharpInvocation.Member.Name == "Invoke" || */ csharpInvocation.Member.Name == "BeginInvoke" || csharpInvocation.Member.Name == "EndInvoke") && !csharpInvocation.IsExtensionMethodInvocation) { throw new EmitterException(invocationExpression, "Delegate's 'Invoke' methods are not supported. Please use direct delegate invoke."); } if (csharpInvocation.IsExtensionMethodInvocation) { invocationResult = csharpInvocation; isExtensionMethodInvocation = true; var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && resolvedMethod.IsExtensionMethod) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (string.IsNullOrWhiteSpace(inline) && isNative) { invocationResult = null; } } } else { invocationResult = null; } if (this.IsEmptyPartialInvoking(csharpInvocation.Member as IMethod) || IsConditionallyRemoved(invocationExpression, csharpInvocation.Member)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null && (this.IsEmptyPartialInvoking(invocationResult.Member as IMethod) || IsConditionallyRemoved(invocationExpression, invocationResult.Member))) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } if (invocationResult == null) { invocationResult = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter) as InvocationResolveResult; } if (invocationResult != null) { var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && (resolvedMethod.IsExtensionMethod || isObjectLiteral)) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (isExtensionMethodInvocation || isObjectLiteral) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else if (!isNative) { var overloads = OverloadsCollection.Create(this.Emitter, resolvedMethod); if (isObjectLiteral && !resolvedMethod.IsStatic && resolvedMethod.DeclaringType.Kind == TypeKind.Interface) { this.Write("Bridge.getType("); this.WriteThisExtension(invocationExpression.Target); this.Write(")."); } else { string name = BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter) + "."; this.Write(name); } if (isObjectLiteral && !resolvedMethod.IsStatic) { this.Write(JS.Fields.PROTOTYPE + "." + overloads.GetOverloadName() + "." + JS.Funcs.CALL); } else { this.Write(overloads.GetOverloadName()); } var isIgnoreClass = resolvedMethod.DeclaringTypeDefinition != null && this.Emitter.Validator.IsExternalType(resolvedMethod.DeclaringTypeDefinition); int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); this.Emitter.Comma = false; if (isObjectLiteral && !resolvedMethod.IsStatic) { this.WriteThisExtension(invocationExpression.Target); this.Emitter.Comma = true; } if (!isIgnoreClass && !Helpers.IsIgnoreGeneric(resolvedMethod, this.Emitter) && argsInfo.HasTypeArguments) { this.EnsureComma(false); new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); this.Emitter.Comma = true; } if (!isObjectLiteral && resolvedMethod.IsStatic) { this.EnsureComma(false); this.WriteThisExtension(invocationExpression.Target); this.Emitter.Comma = true; } if (invocationExpression.Arguments.Count > 0) { this.EnsureComma(false); } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); this.WriteCloseParentheses(); } if (!string.IsNullOrWhiteSpace(inline) || !isNative) { this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else if (isNative) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { argsExpressions.First().AcceptVisitor(this.Emitter); this.WriteDot(); string name = this.Emitter.GetEntityName(resolvedMethod); this.Write(name); int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions.Skip(1), paramsArg, invocationExpression, openPos).Emit(); this.WriteCloseParentheses(); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } } } var proto = false; if (targetMember != null && targetMember.Target is BaseReferenceExpression) { var rr = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter) as MemberResolveResult; if (rr != null) { proto = rr.IsVirtualCall; /*var method = rr.Member as IMethod; * if (method != null && method.IsVirtual) * { * proto = true; * } * else * { * var prop = rr.Member as IProperty; * * if (prop != null && prop.IsVirtual) * { * proto = true; * } * }*/ } } if (proto) { var baseType = this.Emitter.GetBaseMethodOwnerTypeDefinition(targetMember.MemberName, targetMember.TypeArguments.Count); bool isIgnore = this.Emitter.Validator.IsExternalType(baseType); if (isIgnore) { //throw (System.Exception)this.Emitter.CreateException(targetMember.Target, "Cannot call base method, because parent class code is ignored"); } bool needComma = false; var resolveResult = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter); string name = null; if (this.Emitter.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.Emitter.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } string baseMethod; bool isIgnoreGeneric = false; if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; baseMethod = OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(); isIgnoreGeneric = Helpers.IsIgnoreGeneric(invocationResult.Member, this.Emitter); } else if (resolveResult is MemberResolveResult) { MemberResolveResult memberResult = (MemberResolveResult)resolveResult; baseMethod = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); isIgnoreGeneric = Helpers.IsIgnoreGeneric(memberResult.Member, this.Emitter); } else { baseMethod = targetMember.MemberName; baseMethod = this.Emitter.AssemblyInfo.PreserveMemberCase ? baseMethod : Object.Net.Utilities.StringUtils.ToLowerCamelCase(baseMethod); } this.Write(name, "." + JS.Fields.PROTOTYPE + ".", baseMethod); this.WriteCall(); this.WriteOpenParentheses(); this.WriteThis(); this.Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } needComma = false; foreach (var arg in argsExpressions) { if (arg == null) { continue; } this.EnsureComma(false); if (needComma) { this.WriteComma(); } needComma = true; arg.AcceptVisitor(this.Emitter); } this.Emitter.Comma = false; this.WriteCloseParentheses(); } else { var dynamicResolveResult = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter) as DynamicInvocationResolveResult; if (dynamicResolveResult != null) { var group = dynamicResolveResult.Target as MethodGroupResolveResult; if (group != null && group.Methods.Count() > 1) { throw new EmitterException(invocationExpression, "Cannot compile this dynamic invocation because there are two or more method overloads with the same parameter count. To work around this limitation, assign the dynamic value to a non-dynamic variable before use or call a method with different parameter count"); } } var targetResolveResult = this.Emitter.Resolver.ResolveNode(invocationExpression.Target, this.Emitter); var invocationResolveResult = targetResolveResult as MemberResolveResult; IMethod method = null; if (invocationResolveResult != null) { method = invocationResolveResult.Member as IMethod; } if (this.IsEmptyPartialInvoking(method) || IsConditionallyRemoved(invocationExpression, method)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } bool isIgnore = method != null && method.DeclaringTypeDefinition != null && this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition); bool needExpand = false; if (method != null) { string paramsName = null; var paramsParam = method.Parameters.FirstOrDefault(p => p.IsParams); if (paramsParam != null) { paramsName = paramsParam.Name; } if (paramsName != null) { if (csharpInvocation != null && !csharpInvocation.IsExpandedForm) { needExpand = true; } } } int count = this.Emitter.Writers.Count; invocationExpression.Target.AcceptVisitor(this.Emitter); if (this.Emitter.Writers.Count > count) { var writer = this.Emitter.Writers.Pop(); if (method != null && method.IsExtensionMethod) { StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; } else if (writer.ThisArg != null) { argsInfo.ThisArgument = writer.ThisArg; } new InlineArgumentsBlock(this.Emitter, argsInfo, writer.InlineCode) { IgnoreRange = writer.IgnoreRange }.Emit(); var result = this.Emitter.Output.ToString(); this.Emitter.Output = writer.Output; this.Emitter.IsNewLine = writer.IsNewLine; this.Write(result); if (writer.Callback != null) { writer.Callback.Invoke(); } } else { if (needExpand && isIgnore) { this.Write("." + JS.Funcs.APPLY); } int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); bool isIgnoreGeneric = false; var invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null) { isIgnoreGeneric = Helpers.IsIgnoreGeneric(invocationResult.Member, this.Emitter); } if (needExpand && isIgnore) { StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); var thisArg = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; this.Write(thisArg); this.Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } this.EnsureComma(false); if (argsExpressions.Length > 1) { this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions.Take(argsExpressions.Length - 1).ToArray(), paramsArg, invocationExpression, openPos).Emit(); this.WriteCloseBracket(); this.Write(".concat("); new ExpressionListBlock(this.Emitter, new Expression[] { argsExpressions[argsExpressions.Length - 1] }, paramsArg, invocationExpression, openPos).Emit(); this.Write(")"); } else { new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression, -1).Emit(); } } else { this.Emitter.Comma = false; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } if (invocationExpression.Arguments.Count > 0) { this.EnsureComma(false); } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); } this.Emitter.Comma = false; this.WriteCloseParentheses(); } } Helpers.CheckValueTypeClone(this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter), invocationExpression, this, pos); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; }
public virtual string GetCustomTypeName(TypeDefinition type, IEmitter emitter) { if (this._stack.Contains(type)) { return(null); } var nsAtrr = this.GetAttribute(type.CustomAttributes, Translator.Bridge_ASSEMBLY + ".NamespaceAttribute"); bool hasNs = nsAtrr != null && nsAtrr.ConstructorArguments.Count > 0; var nameAttr = this.GetAttribute(type.CustomAttributes, Translator.Bridge_ASSEMBLY + ".NameAttribute"); string name = null; bool changeCase = false; if (nameAttr != null && nameAttr.ConstructorArguments.Count > 0) { if (nameAttr.ConstructorArguments[0].Value is string) { name = (string)nameAttr.ConstructorArguments[0].Value; } else if (nameAttr.ConstructorArguments[0].Value is bool) { var boolValue = (bool)nameAttr.ConstructorArguments[0].Value; if (boolValue) { if (hasNs) { changeCase = true; } else { this._stack.Push(type); name = BridgeTypes.ToJsName(type, emitter); var i = name.LastIndexOf("."); if (i > -1) { char[] chars = name.ToCharArray(); chars[i + 1] = Char.ToLowerInvariant(chars[i + 1]); name = new string(chars); } else { name = name.ToLowerCamelCase(); } this._stack.Pop(); return(name); } } } } if (!string.IsNullOrEmpty(name)) { return(name); } if (hasNs) { var arg = nsAtrr.ConstructorArguments[0]; name = ""; if (arg.Value is string) { name = arg.Value.ToString(); } if (arg.Value is bool && ((bool)arg.Value)) { return(null); } if (type.IsNested) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(type); } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(changeCase ? type.Name.ToLowerCamelCase() : type.Name); return(name); } if (this.HasAttribute(type.CustomAttributes, Translator.Bridge_ASSEMBLY + ".ObjectLiteralAttribute")) { return("Object"); } return(null); }
protected virtual void EmitMethods(Dictionary <string, List <MethodDeclaration> > methods, Dictionary <string, List <EntityDeclaration> > properties, Dictionary <OperatorType, List <OperatorDeclaration> > operators) { var names = new List <string>(properties.Keys); foreach (var name in names) { var props = properties[name]; foreach (var prop in props) { if (prop is PropertyDeclaration) { this.Emitter.VisitPropertyDeclaration((PropertyDeclaration)prop); } else if (prop is CustomEventDeclaration) { this.Emitter.VisitCustomEventDeclaration((CustomEventDeclaration)prop); } else if (prop is IndexerDeclaration) { this.Emitter.VisitIndexerDeclaration((IndexerDeclaration)prop); } } } names = new List <string>(methods.Keys); foreach (var name in names) { this.EmitMethodsGroup(methods[name]); } if (operators != null) { var ops = new List <OperatorType>(operators.Keys); foreach (var op in ops) { this.EmitOperatorGroup(operators[op]); } } if (this.TypeInfo.ClassType == ClassType.Struct) { if (!this.StaticBlock) { this.EmitStructMethods(); } else { var typeDef = this.Emitter.GetTypeDefinition(); string structName = this.Emitter.Validator.GetCustomTypeName(typeDef, this.Emitter); if (structName.IsEmpty()) { structName = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); } //this.EnsureComma(); this.EnsureNewLine(); const string functionName = TransformCtx.DefaultString; this.Write(functionName, " = function () return " + structName + CtorOpenCloseParentheses + " end"); this.Emitter.Comma = true; TransformCtx.CurClassMethodNames.Add(new TransformCtx.MethodInfo() { Name = functionName }); } } }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; this.isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id) && resolveResult is LocalResolveResult) { var lrr = (LocalResolveResult)resolveResult; if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(lrr.Variable) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[lrr.Variable]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); return; } if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); /*if (this.Emitter.Validator.IsIgnoreType(resolveResult.Type.GetDefinition()) || resolveResult.Type.Kind == TypeKind.Enum) * { * this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); * } * else * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(resolveResult.Type, this.Emitter) + ")"); * }*/ return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; var isInvoke = identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression); if (memberResult != null && memberResult.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(memberResult.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inlineCode = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } if (string.IsNullOrEmpty(inlineCode) && memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var method = (IMethod)memberResult.Member; if (method.TypeArguments.Count > 0) { inlineCode = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasInline && inlineCode.StartsWith("<self>")) { hasThis = true; inlineCode = inlineCode.Substring(6); } if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); /*if (!this.Emitter.Validator.IsIgnoreType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum) * { * this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); * } * else * { * this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { this.WriteThis(); } var oldInline = inlineCode; var thisArg = this.Emitter.Output.ToString(); int thisIndex = inlineCode.IndexOf("{this}"); inlineCode = inlineCode.Replace("{this}", thisArg); this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode, null, thisArg, range); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), oldInline, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else { this.Write(inlineCode); } } return; } if (hasInline) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else { this.Write(inlineCode); } } return; } string appendAdditionalCode = null; if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { if (!string.IsNullOrEmpty(inlineCode)) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, identifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else { var resolvedMethod = (IMethod)memberResult.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_BIND); this.WriteOpenParentheses(); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(memberResult.Member) && this.Emitter.IsInlineConst(memberResult.Member)) { this.WriteScript(memberResult.ConstantValue); return; } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { //this.Write(inlineCode); if (resolveResult is InvocationResolveResult || (memberResult.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } else if (Helpers.IsFieldProperty(memberResult.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.DEC); } this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.DEC); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); } else { trg = "this"; } this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), "()", "{0})")); } else { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is DefaultResolvedEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); this.Write( OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member, true)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); string name = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); if (isRefArg) { this.WriteScript(name); } else { this.Write(name); } } else { this.Write(resolveResult.ToString()); } } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); }
protected virtual void EmitCtorForInstantiableClass() { var baseType = this.Emitter.GetBaseTypeDefinition(); var typeDef = this.Emitter.GetTypeDefinition(); var isObjectLiteral = this.Emitter.Validator.IsObjectLiteral(typeDef); var isPlainMode = this.Emitter.Validator.GetObjectCreateMode(typeDef) == 0; var ctorWrappers = isObjectLiteral ? new string[0] : this.EmitInitMembers().ToArray(); if (!this.TypeInfo.HasRealInstantiable(this.Emitter) && ctorWrappers.Length == 0 || isObjectLiteral && isPlainMode) { if (this.ctorHeader) { this.WriteNewLine(); this.EndBlock(); } return; } bool forceDefCtor = isObjectLiteral && this.Emitter.Validator.GetObjectCreateMode(typeDef) == 1 && this.TypeInfo.Ctors.Count == 0; if (typeDef.IsValueType || forceDefCtor || (this.TypeInfo.Ctors.Count == 0 && ctorWrappers.Length > 0)) { this.TypeInfo.Ctors.Add(new ConstructorDeclaration { Modifiers = Modifiers.Public, Body = new BlockStatement() }); } if (!this.ctorHeader && this.TypeInfo.Ctors.Count > 0) { this.EnsureComma(); this.ctorHeader = true; this.Write(JS.Fields.CTORS); this.WriteColon(); this.BeginBlock(); } this.Emitter.InConstructor = true; foreach (var ctor in this.TypeInfo.Ctors) { var oldRules = this.Emitter.Rules; if (ctor.Body.HasChildren) { var rr = this.Emitter.Resolver.ResolveNode(ctor, this.Emitter) as MemberResolveResult; if (rr != null) { this.Emitter.Rules = Rules.Get(this.Emitter, rr.Member); } } this.EnsureComma(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(ctor.Parameters, ctor.Body); var ctorName = JS.Funcs.CONSTRUCTOR; if (this.TypeInfo.Ctors.Count > 1 && ctor.Parameters.Count > 0) { var overloads = OverloadsCollection.Create(this.Emitter, ctor); ctorName = overloads.GetOverloadName(); } XmlToJsDoc.EmitComment(this, ctor); this.Write(ctorName); this.WriteColon(); this.WriteFunction(); int pos = this.Emitter.Output.Length; this.EmitMethodParameters(ctor.Parameters, null, ctor); var ctorParams = this.Emitter.Output.ToString().Substring(pos); this.WriteSpace(); this.BeginBlock(); var len = this.Emitter.Output.Length; var requireNewLine = false; var noThisInvocation = ctor.Initializer == null || ctor.Initializer.IsNull || ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base; IWriterInfo oldWriter = null; if (ctorWrappers.Length > 0 && noThisInvocation) { oldWriter = this.SaveWriter(); this.NewWriter(); } this.ConvertParamsToReferences(ctor.Parameters); if (len != this.Emitter.Output.Length) { requireNewLine = true; } if (isObjectLiteral) { if (requireNewLine) { this.WriteNewLine(); } this.Write("var " + JS.Vars.D_THIS + " = "); var isBaseObjectLiteral = baseType != null && this.Emitter.Validator.IsObjectLiteral(baseType); if (isBaseObjectLiteral && baseType != null && (!this.Emitter.Validator.IsExternalType(baseType) || this.Emitter.Validator.IsBridgeClass(baseType)) || (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This)) { this.EmitBaseConstructor(ctor, ctorName, true); } else if (isBaseObjectLiteral && baseType != null && ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { this.EmitExternalBaseCtor(ctor, ref requireNewLine); } else { this.Write("{ };"); } this.WriteNewLine(); string name = this.Emitter.Validator.GetCustomTypeName(typeDef, this.Emitter, false); if (name.IsEmpty()) { name = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); } this.Write(JS.Vars.D_THIS + "." + JS.Funcs.GET_TYPE + " = function () { return " + name + "; };"); this.WriteNewLine(); this.Write("(function ()"); this.BeginBlock(); requireNewLine = false; } var beginPosition = this.Emitter.Output.Length; if (noThisInvocation) { if (requireNewLine) { this.WriteNewLine(); } if (isObjectLiteral) { var fieldBlock = new FieldBlock(this.Emitter, this.TypeInfo, false, false, true); fieldBlock.Emit(); var properties = this.TypeInfo.InstanceProperties; var names = new List <string>(properties.Keys); foreach (var name in names) { var props = properties[name]; foreach (var prop in props) { var p = prop as PropertyDeclaration; if (p != null) { if (p.Getter.Body.IsNull && p.Setter.Body.IsNull) { continue; } this.Write(JS.Types.Object.DEFINEPROPERTY); this.WriteOpenParentheses(); this.Write("this, "); this.WriteScript(OverloadsCollection.Create(this.Emitter, p).GetOverloadName()); this.WriteComma(); this.Emitter.Comma = false; this.BeginBlock(); var memberResult = this.Emitter.Resolver.ResolveNode(p, this.Emitter) as MemberResolveResult; var block = new VisitorPropertyBlock(this.Emitter, p); block.EmitPropertyMethod(p, p.Getter, ((IProperty)memberResult.Member).Getter, false, true); block.EmitPropertyMethod(p, p.Setter, ((IProperty)memberResult.Member).Setter, true, true); this.EnsureComma(true); this.Write(JS.Fields.ENUMERABLE + ": true"); this.WriteNewLine(); this.EndBlock(); this.WriteCloseParentheses(); this.Write(";"); this.WriteNewLine(); } } } } else { this.Write("this." + JS.Funcs.INITIALIZE + "();"); requireNewLine = true; } } if (!isObjectLiteral) { if (baseType != null && (!this.Emitter.Validator.IsExternalType(baseType) || this.Emitter.Validator.IsBridgeClass(baseType)) || (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This)) { if (requireNewLine) { this.WriteNewLine(); requireNewLine = false; } this.EmitBaseConstructor(ctor, ctorName, false); } else if (baseType != null && ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { this.EmitExternalBaseCtor(ctor, ref requireNewLine); } } var script = this.Emitter.GetScript(ctor); var hasAdditionalIndent = false; if (script == null) { if (ctor.Body.HasChildren) { if (requireNewLine) { this.WriteNewLine(); } ctor.Body.AcceptChildren(this.Emitter); if (!this.Emitter.IsAsync) { hasAdditionalIndent = this.Emitter.TempVariables.Count > 0; this.EmitTempVars(beginPosition, true); } } else if (requireNewLine) { this.WriteNewLine(); } } else { if (requireNewLine) { this.WriteNewLine(); } this.WriteLines(script); } if (oldWriter != null) { this.WrapBody(oldWriter, ctorWrappers, ctorParams); } if (isObjectLiteral) { if (requireNewLine) { this.WriteNewLine(); } this.EndBlock(); this.Write(")." + JS.Funcs.CALL + "(" + JS.Vars.D_THIS + ");"); this.WriteNewLine(); this.Write("return " + JS.Vars.D_THIS + ";"); this.WriteNewLine(); } if (hasAdditionalIndent) { this.Indent(); } this.EndBlock(); this.Emitter.Comma = true; this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); this.Emitter.Rules = oldRules; } this.Emitter.InConstructor = false; if (this.ctorHeader) { this.WriteNewLine(); this.EndBlock(); } }
protected void VisitForeachStatement(bool?replaceAwaiterByVar = null) { ForeachStatement foreachStatement = this.ForeachStatement; var jumpStatements = this.Emitter.JumpStatements; this.Emitter.JumpStatements = null; if (foreachStatement.EmbeddedStatement is EmptyStatement) { return; } this.WriteSourceMapName(foreachStatement.VariableName); var iteratorVar = this.GetTempVarName(); var iteratorName = this.AddLocal(iteratorVar, null, AstType.Null); var rr = (ForEachResolveResult)this.Emitter.Resolver.ResolveNode(foreachStatement, this.Emitter); var get_rr = rr.GetEnumeratorCall as InvocationResolveResult; var in_rr = this.Emitter.Resolver.ResolveNode(foreachStatement.InExpression, this.Emitter); var inline = get_rr != null?this.Emitter.GetInline(get_rr.Member) : null; var checkEnum = in_rr.Type.Kind != TypeKind.Array && !in_rr.Type.IsKnownType(KnownTypeCode.String) && !in_rr.Type.IsKnownType(KnownTypeCode.Array); var isGenericEnumerable = rr.CollectionType.IsParameterized && rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable"; var emitInline = checkEnum && !isGenericEnumerable && inline != null; this.Write(iteratorName, " = "); if (!emitInline) { this.Write(JS.Funcs.BRIDGE_GET_ENUMERATOR); this.WriteOpenParentheses(); foreachStatement.InExpression.AcceptVisitor(this.Emitter); } if (checkEnum) { if (isGenericEnumerable) { this.WriteComma(false); this.Write(BridgeTypes.ToJsName(((ParameterizedType)rr.CollectionType).TypeArguments[0], this.Emitter)); } else if (get_rr != null) { if (inline != null) { var argsInfo = new ArgumentsInfo(this.Emitter, foreachStatement.InExpression, get_rr); new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { var name = OverloadsCollection.Create(this.Emitter, get_rr.Member).GetOverloadName(); if (name != "GetEnumerator" && name != "System$Collections$IEnumerable$GetEnumerator") { this.WriteComma(false); this.WriteScript(name); } } } } if (!emitInline) { this.WriteCloseParentheses(); } this.WriteSemiColon(); this.WriteNewLine(); this.WriteTry(); this.BeginBlock(); this.WriteWhile(); this.WriteOpenParentheses(); this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.MOVE_NEXT); this.WriteOpenCloseParentheses(); this.WriteCloseParentheses(); this.WriteSpace(); this.BeginBlock(); this.PushLocals(); Action ac = () => { bool isReferenceLocal = false; if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(rr.ElementVariable)) { isReferenceLocal = this.Emitter.LocalsMap[rr.ElementVariable].EndsWith(".v"); } var varName = this.AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType); this.WriteVar(); this.Write(varName + " = "); if (isReferenceLocal) { this.Write("{ v : "); } string castCode = this.GetCastCode(rr.ElementType, rr.ElementVariable.Type); if (castCode != null) { this.EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode); } else if (this.CastMethod != null) { this.Write(BridgeTypes.ToJsName(this.CastMethod.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, this.CastMethod).GetOverloadName()); this.WriteOpenParentheses(); int pos = this.Emitter.Output.Length; this.Write(iteratorName + "." + JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); this.WriteCloseParentheses(); } else { var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type); if (needCast) { this.Write(JS.Funcs.BRIDGE_CAST); this.WriteOpenParentheses(); } int pos = this.Emitter.Output.Length; this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); if (needCast) { this.Write(", ", BridgeTypes.ToJsName(rr.ElementVariable.Type, this.Emitter), ")"); } } if (isReferenceLocal) { this.Write(" }"); } this.WriteSemiColon(); this.WriteNewLine(); }; this.Emitter.BeforeBlock = ac; BlockStatement block = foreachStatement.EmbeddedStatement as BlockStatement; if (replaceAwaiterByVar.HasValue) { this.Emitter.ReplaceAwaiterByVar = replaceAwaiterByVar.Value; } if (block != null) { this.Emitter.NoBraceBlock = block; } foreachStatement.EmbeddedStatement.AcceptVisitor(this.Emitter); this.PopLocals(); if (!this.Emitter.IsNewLine) { this.WriteNewLine(); } this.EndBlock(); this.WriteNewLine(); this.EndBlock(); this.WriteSpace(); this.WriteFinally(); this.BeginBlock(); this.Write($"if ({JS.Types.Bridge.IS}({iteratorName}, {JS.Types.System.IDisposable.NAME})) "); this.BeginBlock(); this.Write($"{iteratorName}.{JS.Types.System.IDisposable.INTERFACE_DISPOSE}();"); this.WriteNewLine(); this.EndBlock(); this.WriteNewLine(); this.EndBlock(); this.Emitter.JumpStatements = jumpStatements; }
protected virtual void EmitBaseConstructor(ConstructorDeclaration ctor, string ctorName, bool isObjectLiteral) { var initializer = ctor.Initializer != null && !ctor.Initializer.IsNull ? ctor.Initializer : new ConstructorInitializer() { ConstructorInitializerType = ConstructorInitializerType.Base }; bool appendScope = false; bool isBaseObjectLiteral = false; if (initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { var baseType = this.Emitter.GetBaseTypeDefinition(); //var baseName = JS.Funcs.CONSTRUCTOR; string baseName = null; isBaseObjectLiteral = this.Emitter.Validator.IsObjectLiteral(baseType); if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } } string name = null; if (this.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } if (!isObjectLiteral && isBaseObjectLiteral) { this.Write(JS.Types.Bridge.COPY_PROPERTIES); this.WriteOpenParentheses(); this.Write("this, "); } this.Write(name, "."); if (baseName == null) { var baseIType = this.Emitter.BridgeTypes.Get(baseType).Type; var baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.Count == 0); if (baseCtor == null) { baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.All(p => p.IsOptional)); } if (baseCtor == null) { baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.Count == 1 && c.Parameters.First().IsParams); } if (baseCtor != null) { baseName = OverloadsCollection.Create(this.Emitter, baseCtor).GetOverloadName(); } else { baseName = JS.Funcs.CONSTRUCTOR; } } this.Write(baseName); if (!isObjectLiteral) { this.WriteCall(); appendScope = true; } } else { // this.WriteThis(); string name = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); this.Write(name); this.WriteDot(); var baseName = JS.Funcs.CONSTRUCTOR; var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } this.Write(baseName); if (!isObjectLiteral) { this.WriteCall(); appendScope = true; } } int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); if (appendScope) { this.WriteThis(); if (initializer.Arguments.Count > 0) { this.WriteComma(); } } if (initializer.Arguments.Count > 0) { var argsInfo = new ArgumentsInfo(this.Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } if (!isObjectLiteral && isBaseObjectLiteral) { this.WriteCloseParentheses(); } this.WriteCloseParentheses(); this.WriteSemiColon(); if (!isObjectLiteral) { this.WriteNewLine(); } }
protected void VisitAsyncForeachStatement() { ForeachStatement foreachStatement = this.ForeachStatement; if (foreachStatement.EmbeddedStatement is EmptyStatement) { return; } var oldValue = this.Emitter.ReplaceAwaiterByVar; var jumpStatements = this.Emitter.JumpStatements; this.Emitter.JumpStatements = new List <IJumpInfo>(); this.WriteAwaiters(foreachStatement.InExpression); bool containsAwaits = false; var awaiters = this.GetAwaiters(foreachStatement.EmbeddedStatement); if (awaiters != null && awaiters.Length > 0) { containsAwaits = true; } this.Emitter.ReplaceAwaiterByVar = true; if (!containsAwaits) { this.VisitForeachStatement(oldValue); return; } var iteratorName = this.AddLocal(this.GetTempVarName(), null, AstType.Null); var for_rr = (ForEachResolveResult)this.Emitter.Resolver.ResolveNode(foreachStatement, this.Emitter); var get_rr = for_rr.GetEnumeratorCall as InvocationResolveResult; var in_rr = this.Emitter.Resolver.ResolveNode(foreachStatement.InExpression, this.Emitter); var inline = get_rr != null?this.Emitter.GetInline(get_rr.Member) : null; var checkEnum = in_rr.Type.Kind != TypeKind.Array && !in_rr.Type.IsKnownType(KnownTypeCode.String) && !in_rr.Type.IsKnownType(KnownTypeCode.Array); var isGenericEnumerable = for_rr.CollectionType.IsParameterized && for_rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable"; var emitInline = checkEnum && !isGenericEnumerable && inline != null; this.Write(iteratorName, " = "); if (!emitInline) { this.Write(JS.Funcs.BRIDGE_GET_ENUMERATOR); this.WriteOpenParentheses(); foreachStatement.InExpression.AcceptVisitor(this.Emitter); } if (checkEnum) { if (for_rr.CollectionType.IsParameterized && for_rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable") { this.WriteComma(false); this.Write(BridgeTypes.ToJsName(((ParameterizedType)for_rr.CollectionType).TypeArguments[0], this.Emitter)); } else if (get_rr != null) { if (inline != null) { var argsInfo = new ArgumentsInfo(this.Emitter, foreachStatement.InExpression, get_rr); new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { var name = OverloadsCollection.Create(this.Emitter, get_rr.Member).GetOverloadName(); if (name != "GetEnumerator" && name != "System$Collections$IEnumerable$GetEnumerator") { this.WriteComma(false); this.WriteScript(name); } } } } this.Emitter.ReplaceAwaiterByVar = oldValue; if (!emitInline) { this.WriteCloseParentheses(); } this.WriteSemiColon(); this.WriteNewLine(); this.Write(JS.Vars.ASYNC_STEP + " = " + this.Emitter.AsyncBlock.Step + ";"); this.WriteNewLine(); this.Write("continue;"); this.WriteNewLine(); IAsyncStep conditionStep = this.Emitter.AsyncBlock.AddAsyncStep(); this.WriteIf(); this.WriteOpenParentheses(); this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.MOVE_NEXT); this.WriteOpenCloseParentheses(); this.WriteCloseParentheses(); this.WriteSpace(); this.BeginBlock(); this.PushLocals(); var varName = this.AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType); this.WriteVar(); this.Write(varName + " = "); var rr = this.Emitter.Resolver.ResolveNode(foreachStatement, this.Emitter) as ForEachResolveResult; bool isReferenceLocal = false; if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(rr.ElementVariable)) { isReferenceLocal = this.Emitter.LocalsMap[rr.ElementVariable].EndsWith(".v"); } if (isReferenceLocal) { this.Write("{ v : "); } string castCode = this.GetCastCode(rr.ElementType, rr.ElementVariable.Type); if (castCode != null) { this.EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode); } else if (this.CastMethod != null) { this.Write(BridgeTypes.ToJsName(this.CastMethod.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, this.CastMethod).GetOverloadName()); this.WriteOpenParentheses(); var pos = this.Emitter.Output.Length; this.Write(iteratorName + "." + JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); this.WriteCloseParentheses(); } else { var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type); if (needCast) { this.Write(JS.Funcs.BRIDGE_CAST); this.WriteOpenParentheses(); } var pos = this.Emitter.Output.Length; this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); if (needCast) { this.Write(", ", BridgeTypes.ToJsName(rr.ElementVariable.Type, this.Emitter), ")"); } } if (isReferenceLocal) { this.Write(" }"); } this.WriteSemiColon(); this.WriteNewLine(); this.Write(JS.Vars.ASYNC_STEP + " = " + this.Emitter.AsyncBlock.Step + ";"); this.WriteNewLine(); this.Write("continue;"); BlockStatement block = foreachStatement.EmbeddedStatement as BlockStatement; var writer = this.SaveWriter(); this.Emitter.AsyncBlock.AddAsyncStep(); this.Emitter.IgnoreBlock = foreachStatement.EmbeddedStatement; var startCount = this.Emitter.AsyncBlock.Steps.Count; if (block != null) { block.AcceptChildren(this.Emitter); } else { foreachStatement.EmbeddedStatement.AcceptVisitor(this.Emitter); } IAsyncStep loopStep = null; if (this.Emitter.AsyncBlock.Steps.Count > startCount) { loopStep = this.Emitter.AsyncBlock.Steps.Last(); loopStep.JumpToStep = conditionStep.Step; } this.RestoreWriter(writer); if (!AbstractEmitterBlock.IsJumpStatementLast(this.Emitter.Output.ToString())) { this.Write(JS.Vars.ASYNC_STEP + " = " + conditionStep.Step + ";"); this.WriteNewLine(); this.Write("continue;"); this.WriteNewLine(); } this.PopLocals(); this.WriteNewLine(); this.EndBlock(); this.WriteNewLine(); var nextStep = this.Emitter.AsyncBlock.AddAsyncStep(); conditionStep.JumpToStep = nextStep.Step; if (this.Emitter.JumpStatements.Count > 0) { this.Emitter.JumpStatements.Sort((j1, j2) => - j1.Position.CompareTo(j2.Position)); foreach (var jump in this.Emitter.JumpStatements) { jump.Output.Insert(jump.Position, jump.Break ? nextStep.Step : conditionStep.Step); } } this.Emitter.JumpStatements = jumpStatements; }
protected virtual void WriteNestedTypes() { if (this.NestedTypes != null && this.NestedTypes.Any()) { if (!this.Emitter.IsNewLine) { this.WriteNewLine(); } var typeDef = this.Emitter.GetTypeDefinition(); string name = this.Emitter.Validator.GetCustomTypeName(typeDef, this.Emitter); if (name.IsEmpty()) { name = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter, true, true); } this.Write("module "); this.Write(name); this.WriteSpace(); this.BeginBlock(); var last = this.NestedTypes.LastOrDefault(); foreach (var nestedType in this.NestedTypes) { this.Emitter.Translator.EmitNode = nestedType.TypeDeclaration; if (nestedType.IsObjectLiteral) { continue; } ITypeInfo typeInfo; if (this.Emitter.TypeInfoDefinitions.ContainsKey(nestedType.Key)) { typeInfo = this.Emitter.TypeInfoDefinitions[nestedType.Key]; nestedType.Module = typeInfo.Module; nestedType.FileName = typeInfo.FileName; nestedType.Dependencies = nestedType.Dependencies; typeInfo = nestedType; } else { typeInfo = nestedType; } this.Emitter.TypeInfo = nestedType; var nestedTypes = this.AllTypes.Where(t => t.ParentType == nestedType); new ClassBlock(this.Emitter, this.Emitter.TypeInfo, nestedTypes, this.AllTypes).Emit(); this.WriteNewLine(); if (nestedType != last) { this.WriteNewLine(); } } this.EndBlock(); } }
protected virtual void WriteObjectInitializer(IEnumerable <Expression> expressions, bool preserveMemberCase, TypeDefinition type, InvocationResolveResult rr) { bool needComma = false; List <string> names = new List <string>(); if (expressions != null) { foreach (Expression item in expressions) { NamedExpression namedExression = item as NamedExpression; NamedArgumentExpression namedArgumentExpression = item as NamedArgumentExpression; string name = namedExression != null ? namedExression.Name : namedArgumentExpression.Name; if (!preserveMemberCase) { name = Object.Net.Utilities.StringUtils.ToLowerCamelCase(name); } var itemrr = this.Emitter.Resolver.ResolveNode(item, this.Emitter) as MemberResolveResult; if (itemrr != null) { var oc = OverloadsCollection.Create(this.Emitter, itemrr.Member); oc.CancelChangeCase = this.Emitter.IsNativeMember(itemrr.Member.FullName) ? false : preserveMemberCase; name = oc.GetOverloadName(); } if (needComma) { this.WriteComma(); } needComma = true; Expression expression = namedExression != null ? namedExression.Expression : namedArgumentExpression.Expression; this.Write(name, ": "); expression.AcceptVisitor(this.Emitter); names.Add(name); } } if (this.Emitter.Validator.IsObjectLiteral(type)) { var key = BridgeTypes.GetTypeDefinitionKey(type); var tinfo = this.Emitter.Types.FirstOrDefault(t => t.Key == key); if (tinfo == null) { return; } var itype = tinfo.Type as ITypeDefinition; var mode = 0; if (rr != null) { if (rr.Member.Parameters.Count == 1 && rr.Member.Parameters.First().Type.FullName == "Bridge.DefaultValueMode") { var arg = rr.Arguments.FirstOrDefault(); if (arg != null && arg.ConstantValue != null) { mode = (int)arg.ConstantValue; } } else if (itype != null) { var attr = this.Emitter.Validator.GetAttribute(itype.Attributes, Translator.Bridge_ASSEMBLY + ".ObjectLiteralAttribute"); if (attr.PositionalArguments.Count > 0) { var value = attr.PositionalArguments.First().ConstantValue; if (value != null && value is int) { mode = (int)value; } } } } if (mode != 0) { var members = tinfo.InstanceConfig.Fields.Concat(tinfo.InstanceConfig.Properties); if (members.Any()) { foreach (var member in members) { if (mode == 1 && (member.VarInitializer == null || member.VarInitializer.Initializer.IsNull)) { continue; } var name = member.GetName(this.Emitter); if (!preserveMemberCase) { name = Object.Net.Utilities.StringUtils.ToLowerCamelCase(name); } if (names.Contains(name)) { continue; } if (needComma) { this.WriteComma(); } needComma = true; this.Write(name, ": "); var primitiveExpr = member.Initializer as PrimitiveExpression; if (primitiveExpr != null && primitiveExpr.Value is AstType) { this.Write(Inspector.GetStructDefaultValue((AstType)primitiveExpr.Value, this.Emitter)); } else { member.Initializer.AcceptVisitor(this.Emitter); } } } } } }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; bool isConstTarget = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (targetrr is ConstantResolveResult) { isConstTarget = true; } var memberTargetrr = targetrr as MemberResolveResult; if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && this.Emitter.Validator.EnumEmitMode(memberTargetrr.Type) == 2) { isConstTarget = true; } if (memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression)) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } if (resolveResult is DynamicInvocationResolveResult) { resolveResult = ((DynamicInvocationResolveResult)resolveResult).Target; } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; var globalTarget = member != null?this.Emitter.IsGlobalTarget(member.Member) : null; if (globalTarget != null && globalTarget.Item1) { var target = globalTarget.Item2; if (!string.IsNullOrWhiteSpace(target)) { bool assign = false; var memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent; var targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression; var assignment = memberExpression as AssignmentExpression; if (assignment != null && assignment.Right == targetExpression) { assign = true; } else { var varInit = memberExpression as VariableInitializer; if (varInit != null && varInit.Initializer == targetExpression) { assign = true; } else if (memberExpression is InvocationExpression) { var targetInvocation = (InvocationExpression)memberExpression; if (targetInvocation.Arguments.Any(a => a == targetExpression)) { assign = true; } } } if (assign) { if (resolveResult is InvocationResolveResult) { this.PushWriter(target); } else { this.Write(target); } return; } } if (resolveResult is InvocationResolveResult) { this.PushWriter(""); } return; } Tuple <bool, bool, string> inlineInfo = member != null?this.Emitter.GetInlineCode(memberReferenceExpression) : null; //string inline = member != null ? this.Emitter.GetInline(member.Member) : null; string inline = inlineInfo != null ? inlineInfo.Item3 : null; bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && inline.Contains("{this}"); if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; inline = inline.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference"); } else { this.Write(inline); } } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member)) { this.WriteScript(member.ConstantValue); } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { var r = new Regex(@"([$\w\.]+)\(\s*\S.*\)"); var match = r.Match(inline); if (match.Success) { this.Write(match.Groups[1].Value); } else { throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference"); } } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as DefaultResolvedTypeDefinition; if (typeDef != null) { var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsIgnoreType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3) { string enumStringName = member.Member.Name; var attr = Helpers.GetInheritedAttribute(member.Member, Translator.Bridge_ASSEMBLY + ".NameAttribute"); if (attr != null) { enumStringName = this.Emitter.GetEntityName(member.Member); } else { switch (enumMode) { case 3: enumStringName = Object.Net.Utilities.StringUtils.ToLowerCamelCase(member.Member.Name); break; case 4: break; case 5: enumStringName = enumStringName.ToLowerInvariant(); break; case 6: enumStringName = enumStringName.ToUpperInvariant(); break; } } this.WriteScript(enumStringName); return; } } } if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition()); if (isNative) { this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); } else { this.Write("Bridge.get(" + BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter) + ")"); } return; } else if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); if (!isStatic) { this.Write(")"); } return; } else { bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } } if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } } var targetResolveResult = targetrr as MemberResolveResult; if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null) { this.WriteDot(); } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { var proto = false; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && member != null) { var prop = member.Member as IProperty; if (prop != null && (prop.IsVirtual || prop.IsOverride)) { proto = true; } } if (Helpers.IsFieldProperty(member.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isNullable = NullableType.IsNullable(member.Member.ReturnType); bool isDecimal = Helpers.IsDecimalType(member.Member.ReturnType, this.Emitter.Resolver); if (isStatement) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } } else { if (targetVar != null) { this.Write(targetVar); } else { if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); this.WriteCloseParentheses(); } } else { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); bool isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement; if (isPreOp) { if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } if (targetVar != null) { this.RemoveTempVar(targetVar); } } else { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { if (targetVar != null) { this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true), proto ? ".call(this, " : "(", targetVar, ".", Helpers.GetPropertyRef(member.Member, this.Emitter, false), proto ? ".call(this)" : "()", "{0})"), () => { this.RemoveTempVar(targetVar); }); } else { var oldWriter = this.SaveWriter(); this.NewWriter(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; var trg = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true), proto ? ".call(this, " : "(", trg, ".", Helpers.GetPropertyRef(member.Member, this.Emitter, false), proto ? ".call(this)" : "()", "{0})")); } } else { if (proto) { this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + ".call(this, {0})"); } else { this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})"); } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst) { this.WriteScript(member.ConstantValue); } else { this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName()); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName()); } } else if (member.Member is DefaultResolvedEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write( OverloadsCollection.Create(this.Emitter, member.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); this.WriteOpenParentheses(); } else { this.Write(this.Emitter.GetEntityName(member.Member, true)); } } else { this.Write(this.Emitter.GetEntityName(member.Member)); } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
protected virtual List <string> WriteObjectInitializer(IList <KeyValuePair <IMember, ResolveResult> > expressions, bool preserveMemberCase, TypeDefinition type, IAttribute attr) { bool needComma = false; List <string> names = new List <string>(); List <string> inlineInit = new List <string>(); if (expressions != null) { foreach (KeyValuePair <IMember, ResolveResult> item in expressions) { var member = item.Key; var preserveCase = !this.Emitter.IsNativeMember(member.FullName) && preserveMemberCase; var name = this.Emitter.GetEntityName(member, preserveCase); var inlineCode = AttributeCreateBlock.GetInlineInit(item, this); if (inlineCode != null) { inlineInit.Add(inlineCode); } else { if (member is IProperty) { name = Helpers.GetPropertyRef(member, this.Emitter, true); } else if (member is IEvent) { name = Helpers.GetEventRef(member, this.Emitter, false); } if (needComma) { this.WriteComma(); } needComma = true; this.Write(name, ": "); AttributeCreateBlock.WriteResolveResult(item.Value, this); names.Add(name); } } } if (this.Emitter.Validator.IsObjectLiteral(type)) { var key = BridgeTypes.GetTypeDefinitionKey(type); var tinfo = this.Emitter.Types.FirstOrDefault(t => t.Key == key); if (tinfo == null) { return(inlineInit); } var itype = tinfo.Type as ITypeDefinition; var mode = 0; if (attr.Constructor != null) { if (attr.Constructor.Parameters.Count == 1 && attr.Constructor.Parameters.First().Type.FullName == "Bridge.DefaultValueMode") { var arg = attr.PositionalArguments.FirstOrDefault(); if (arg != null && arg.ConstantValue != null) { mode = (int)arg.ConstantValue; } } else if (itype != null) { var oattr = this.Emitter.Validator.GetAttribute(itype.Attributes, Translator.Bridge_ASSEMBLY + ".ObjectLiteralAttribute"); if (oattr.PositionalArguments.Count > 0) { var value = oattr.PositionalArguments.First().ConstantValue; if (value is int) { mode = (int)value; } } } } if (mode != 0) { var members = tinfo.InstanceConfig.Fields.Concat(tinfo.InstanceConfig.Properties); if (members.Any()) { foreach (var member in members) { if (mode == 1 && (member.VarInitializer == null || member.VarInitializer.Initializer.IsNull)) { continue; } var name = member.GetName(this.Emitter); if (!preserveMemberCase) { name = Object.Net.Utilities.StringUtils.ToLowerCamelCase(name); } if (names.Contains(name)) { continue; } if (needComma) { this.WriteComma(); } needComma = true; this.Write(name, ": "); var primitiveExpr = member.Initializer as PrimitiveExpression; if (primitiveExpr != null && primitiveExpr.Value is AstType) { this.Write(Inspector.GetStructDefaultValue((AstType)primitiveExpr.Value, this.Emitter)); } else { member.Initializer.AcceptVisitor(this.Emitter); } } } } } return(inlineInit); }