void CheckFormattingCall(InvocationExpression invocationExpression, CSharpInvocationResolveResult invocationResolveResult) { Expression formatArgument; IList <Expression> formatArguments; TextLocation formatStart; // Only check parameters that are of type object: String means it is neccessary, others // means that there is another problem (ie no matching overload of the method). Func <IParameter, Expression, bool> predicate = (parameter, argument) => { var type = parameter.Type; if (type is TypeWithElementType && parameter.IsParams) { type = ((TypeWithElementType)type).ElementType; } var typeDefinition = type.GetDefinition(); if (typeDefinition == null) { return(false); } return(typeDefinition.IsKnownType(KnownTypeCode.Object)); }; if (FormatStringHelper.TryGetFormattingParameters(invocationResolveResult, invocationExpression, out formatArgument, out formatStart, out formatArguments, predicate)) { foreach (var argument in formatArguments) { CheckExpressionInAutoCallContext(argument); } } }
public JsNode VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult res) { if (res.Member.IsConstructor()) { if (res.Type is AnonymousType) { //TODO: check context class JsType.NativeJsons var json = InitializersToJson(res.InitializerStatements, res.Type); var parentType = res.GetParentType(); if (parentType != null && !Sk.UseNativeJsons(parentType)) { return(Js.Member("$CreateAnonymousObject").Invoke(json)); } return(json); } else { return(VisitInvocationResolveResultAsCtor(res)); } } else { return(VisitInvocationResolveResult(res)); } }
static InitializedObjectResolveResult FindInitializedObjectResolveResult(CSharpInvocationResolveResult res) { var init1 = res.InitializerStatements[0]; while (init1 != null && !(init1 is InitializedObjectResolveResult)) { if (init1 is OperatorResolveResult) { init1 = ((OperatorResolveResult)init1).Operands[0]; } else if (init1 is CSharpInvocationResolveResult) { init1 = ((CSharpInvocationResolveResult)init1).TargetResult; } else if (init1 is MemberResolveResult) { init1 = ((MemberResolveResult)init1).TargetResult; } else { throw new NotImplementedException("FindInitializedObjectResolveResult"); } } return((InitializedObjectResolveResult)init1); }
IEnumerable <Expression> GetRedundantArguments(Expression[] arguments, CSharpInvocationResolveResult invocationResolveResult) { var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap(); var resolvedParameters = invocationResolveResult.Member.Parameters; for (int i = arguments.Length - 1; i >= 0; i--) { var parameterIndex = argumentToParameterMap[i]; if (parameterIndex == -1) { // This particular parameter is an error, but keep trying the other ones continue; } var parameter = resolvedParameters[parameterIndex]; var argument = arguments[i]; if (argument is PrimitiveExpression) { if (parameter.IsParams) { // before positional params arguments all optional arguments are needed, otherwise some of the // param arguments will be shifted out of the params into the fixed parameters break; } if (!parameter.IsOptional) { // There can be no optional parameters preceding a required one break; } var argumentResolveResult = ctx.Resolve(argument) as ConstantResolveResult; if (argumentResolveResult == null || parameter.ConstantValue != argumentResolveResult.ConstantValue) { // Stop here since any arguments before this one has to be there // to enable the passing of this argument break; } yield return(argument); } else if (argument is NamedArgumentExpression) { var expression = ((NamedArgumentExpression)argument).Expression as PrimitiveExpression; if (expression == null) { continue; } var expressionResolveResult = ctx.Resolve(expression) as ConstantResolveResult; if (expressionResolveResult == null || parameter.ConstantValue != expressionResolveResult.ConstantValue) { // continue, since there can still be more arguments that are redundant continue; } yield return(argument); } else { // This is a non-constant positional argument => no more redundancies are possible break; } } }
public JNode VisitMemberResolveResult(MemberResolveResult res) { var me = res.Member; JNode node2; bool enumValuesAsNames; if (me == null) //TODO: dynamics { throw new NotImplementedException(); //var node3 = Js.Member(node.MemberName); //if (node.Target != null) // node3.PreviousMember = VisitExpression(node.Target); //return node3; } else if (IsEntityFunctionProperty(res.Member, res))//(Entity)node.entity)) { var pe = (IProperty)me; var xxx = new CSharpInvocationResolveResult(res.TargetResult, pe.Getter, null); node2 = Visit(xxx); return(node2); } else if (me.IsEnumMember() && JMeta.UseJsonEnums(me, out enumValuesAsNames)) { var me2 = (IField)me; if (enumValuesAsNames) { return(J.String(JNaming.JName(me2))); } else { return(J.Value(me2.ConstantValue)); } } //TODO: Support a way to override this (JsField.ConstantInlining=false) else if (res.IsCompileTimeConstant && !me.IsEnumMember()) { return(J.Value(res.ConstantValue)); } else { var node3 = JNaming.JAccess(me); node2 = node3; if (res.TargetResult != null && !me.IsStatic()) { var instanceContext = VisitExpression(res.TargetResult); if (node3.Name.IsNullOrEmpty()) //support Name="" { node2 = instanceContext; } else { node3.PreviousMember = instanceContext; } } } return(node2); }
AstNode ToStaticMethodInvocation(InvocationExpression invocation, MemberReferenceExpression memberReference, CSharpInvocationResolveResult invocationRR) { var newArgumentList = invocation.Arguments.Select(arg => arg.Clone()).ToList(); newArgumentList.Insert(0, memberReference.Target.Clone()); var newTarget = memberReference.Clone() as MemberReferenceExpression; newTarget.Target = new IdentifierExpression(invocationRR.Member.DeclaringType.Name); return(new InvocationExpression(newTarget, newArgumentList)); }
public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression, out Expression formatArgument, out IList <Expression> arguments, Func <IParameter, Expression, bool> argumentFilter) { if (argumentFilter == null) { argumentFilter = (p, e) => true; } formatArgument = null; arguments = new List <Expression>(); var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap(); var resolvedParameters = invocationResolveResult.Member.Parameters; var allArguments = invocationExpression.Arguments.ToArray(); for (int i = 0; i < allArguments.Length; i++) { var parameterIndex = argumentToParameterMap[i]; if (parameterIndex < 0 || parameterIndex >= resolvedParameters.Count) { // No valid mapping for this argument, skip it continue; } var parameter = resolvedParameters[parameterIndex]; var argument = allArguments[i]; if (i == 0 && parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name)) { formatArgument = argument; } else if (formatArgument != null && parameter.IsParams && !invocationResolveResult.IsExpandedForm) { var ace = argument as ArrayCreateExpression; if (ace == null || ace.Initializer.IsNull) { return(false); } foreach (var element in ace.Initializer.Elements) { if (argumentFilter(parameter, element)) { arguments.Add(argument); } } } else if (formatArgument != null && argumentFilter(parameter, argument)) { arguments.Add(argument); } } return(formatArgument != null); }
public static CSharpInvocationResolveResult ToCSharpInvocationResolveResult(this InvocationResolveResult res) { if (res == null) { return(null); } if (res is CSharpInvocationResolveResult) { return((CSharpInvocationResolveResult)res); } var res2 = new CSharpInvocationResolveResult(res.TargetResult, res.Member, res.Arguments, initializerStatements: res.InitializerStatements); res2.Tag = res.Tag; return(res2); }
public override void VisitInvocationExpression(InvocationExpression invocationExpression) { base.VisitInvocationExpression(invocationExpression); if (!CanTransformToExtensionMethodCall(resolver, invocationExpression, out var memberRefExpr, out var target, out var firstArgument)) { return; } var method = (IMethod)invocationExpression.GetSymbol(); if (firstArgument is DirectionExpression dirExpr) { if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out) { return; } firstArgument = dirExpr.Expression; target = firstArgument.GetResolveResult(); dirExpr.Detach(); } else if (firstArgument is NullReferenceExpression) { Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace)); firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach())); } if (invocationExpression.Target is IdentifierExpression identifierExpression) { identifierExpression.Detach(); memberRefExpr = new MemberReferenceExpression(firstArgument.Detach(), method.Name, identifierExpression.TypeArguments.Detach()); invocationExpression.Target = memberRefExpr; } else { memberRefExpr.Target = firstArgument.Detach(); } if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr) { // do not forget to update the CSharpInvocationResolveResult => set IsExtensionMethodInvocation == true invocationExpression.RemoveAnnotations <CSharpInvocationResolveResult>(); var newResolveResult = new CSharpInvocationResolveResult( irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors, isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation, irr.GetArgumentToParameterMap(), irr.InitializerStatements); invocationExpression.AddAnnotation(newResolveResult); } }
public JNode VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult res) { if (res.Member.IsConstructor()) { if (res.Type is AnonymousType) { //TODO: check context class JsType.NativeJsons var json = InitializersToJson(res.InitializerStatements, res.Type); return(json); } else { return(VisitInvocationResolveResultAsCtor(res)); } } else { return(VisitInvocationResolveResult(res)); } }
public static List <ParameterBinding> GetArgumentsForCall2(this CSharpInvocationResolveResult res) { var args = res.Arguments; var callArgs = res.GetArgumentsForCall(); var map = res.GetArgumentToParameterMap(); var prms = res.Member.Parameters; var list = callArgs.Select(t => new ParameterBinding { CallResult = t }).ToList(); var index = -1; foreach (var arg in args) { index++; var index2 = map == null ? index : map[index]; var prm = prms[index2]; var binding = list[index2]; binding.Parameter = prm; binding.ArgResult = arg; } index = 0; foreach (var binding in list) { var prm = prms[index]; if (binding.Parameter == null) { binding.Parameter = prm; } else if (binding.Parameter != prm) { throw new NotImplementedException(); } if (!prm.IsParams) { index++; } } return(list); }
void TransformIntoBaseMethodCallIfNeeded(CSharpInvocationResolveResult res, JInvocationExpression node2) { var target = res.TargetResult as ThisResolveResult; if (target != null && target.CausesNonVirtualInvocation) //base. { //var info = res.GetInfo(); //var node = info.Nodes.FirstOrDefault(); var ce = target.Type;// node.FindThisEntity(); if (ce != null && JMeta.IsExtJsType(ce.GetDefinitionOrArrayType(Compiler))) { node2.Member = J.This().Member("callParent"); if (node2.Arguments.IsNotNullOrEmpty()) { node2.Arguments = new List <JExpression> { J.NewJsonArray(node2.Arguments.ToArray()) } } ; //var me2 = (node2.Member as JsMemberExpression); //me2.Name = "callParent"; return; } IMethod me2; var me = res.Member; if (me is IProperty) { me2 = ((IProperty)me).Getter; } else if (me is IMethod) { me2 = (IMethod)res.Member; } else { throw new Exception("Can't resolve method from member: " + res.Member); } ((JMemberExpression)node2.Member).PreviousMember = J.Member("super"); } }
public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression, out Expression formatArgument, out TextLocation formatStart, out IList <Expression> arguments, Func <IParameter, Expression, bool> argumentFilter) { if (argumentFilter == null) { argumentFilter = (p, e) => true; } formatArgument = null; formatStart = default(TextLocation); arguments = new List <Expression>(); var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap(); var resolvedParameters = invocationResolveResult.Member.Parameters; var allArguments = invocationExpression.Arguments.ToArray(); for (int i = 0; i < allArguments.Length; i++) { var parameterIndex = argumentToParameterMap[i]; if (parameterIndex < 0 || parameterIndex >= resolvedParameters.Count) { // No valid mapping for this parameter, skip it continue; } var parameter = resolvedParameters[parameterIndex]; var argument = allArguments[i]; if (parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name)) { formatArgument = argument; formatStart = argument.StartLocation; } else if ((formatArgument != null || parameter.IsParams) && argumentFilter(parameter, argument)) { arguments.Add(argument); } } return(formatArgument != null); }
private JsNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res) { return(new ResolveResultVisitor_Invcation { Compiler = Compiler, Importer = this, Project = Project }.VisitInvocationResolveResultAsCtor(res)); }
public JsNode VisitMemberResolveResult(MemberResolveResult res) { var me = res.Member; JsNode node2; bool enumValuesAsNames; if (me == null) //TODO: dynamics { throw new NotImplementedException(); //var node3 = Js.Member(node.MemberName); //if (node.Target != null) // node3.PreviousMember = VisitExpression(node.Target); //return node3; } else if (Sk.IsEntityFunctionProperty(res.Member, res))//(Entity)node.entity)) { var pe = (IProperty)me; var xxx = new CSharpInvocationResolveResult(res.TargetResult, pe.Getter, null); var fn = res.GetFirstNode(); qiucw.InvokeRR2Location.Add(xxx, new qiucw.InvocationLocation { FileName = fn.GetFileName(), Line = fn.StartLocation.Line }); { node2 = Visit(xxx); } qiucw.InvokeRR2Location.Remove(xxx); return(node2); } else if (me.IsEnumMember() && Sk.UseJsonEnums(me, out enumValuesAsNames)) { var me2 = (IField)me; if (enumValuesAsNames) { return(Js.String(SkJs.GetEntityJsName(me2))); } else { return(Js.Value(me2.ConstantValue)); } } //TODO: Support a way to override this (JsField.ConstantInlining=false) else if (res.IsCompileTimeConstant && !me.IsEnumMember()) { var nodes = res.GetNodes(); if (nodes.IsNotNullOrEmpty()) { if (nodes[0] != null) { bool isPrimitiveExpr = nodes[0] is PrimitiveExpression; if (!isPrimitiveExpr) { return(Js.Value(res.ConstantValue, string.Format(" /* {0} */", nodes[0].ToString()))); } } } return(Js.Value(res.ConstantValue)); } else { var node3 = SkJs.EntityToMember(me); qiucw.CheckAddInvocation(res, node3.Name); node2 = node3; if (res.TargetResult != null && !me.IsStatic()) { var instanceContext = VisitExpression(res.TargetResult); if (node3.Name.IsNullOrEmpty()) //support Name="" { node2 = instanceContext; } else { node3.PreviousMember = instanceContext; } } } return(node2); }
private JNode VisitInvocationResolveResult(CSharpInvocationResolveResult res) { ////TODO: LET LINQ //var firstNode = res.GetFirstNode(); //if (firstNode != null && firstNode is QueryLetClause) //{ // foreach (var arg in res.Arguments) // { // if (arg.GetInfo() == null) // arg.SetInfo(new ResolveResultInfo { Nodes = { firstNode } }); // } //} var member = res.Member; var me = member as IMethod; if (me == null) { var pe = member as IProperty; if (pe != null) { me = pe.Getter; member = me; } } var att = me != null?JMeta.GetJMethodAttribute(me) : null; if (att != null && att.InlineCode != null) { return(J.Code(att.InlineCode)); } //TODO: move defines locally var condAtt = me.GetMetadata <System.Diagnostics.ConditionalAttribute>(); if (condAtt != null && Compiler != null && Compiler.Defines != null && !Compiler.Defines.Contains(condAtt.ConditionString)) { return(null); } if (att != null && att.OmitCalls) { if (me.IsStatic() && !me.IsExtensionMethod) { return(null); } if (me.IsExtensionMethod && !res.IsExtensionMethodInvocation) { return(null); } if (res.Arguments.IsEmpty() && res.TargetResult != null) { return(VisitExpression(res.TargetResult)); } return(Visit(res.Arguments[0])); } var jsMember = JNaming.JAccess(member); if (res.TargetResult != null && !member.IsStatic() && member.SymbolKind != SymbolKind.Constructor) //TargetResult==null when ctor { var target = VisitExpression(res.TargetResult); if (jsMember.PreviousMember != null) { throw new NotSupportedException(); } jsMember.PreviousMember = target; } var bindings = res.GetArgumentsForCall2(); if (JMeta.OmitOptionalParameters(me)) { bindings.RemoveAll(t => t.ArgResult == null); } if (JMeta.IsNativeParams(me)) { var binding = bindings.Where(t => t.Parameter.IsParams).FirstOrDefault(); if (binding != null) { if (binding.CallResult is ArrayCreateResolveResult) { var arrayRes = (ArrayCreateResolveResult)binding.CallResult; bindings.Remove(binding); if (arrayRes.InitializerElements.IsNotNullOrEmpty()) { foreach (var init in arrayRes.InitializerElements) { var b = binding.Clone(); b.CallResult = init; bindings.Add(b); } } } else { Log.Warn(res.GetFirstNode(), "Invalid params parameter passed to method with NativeParams=true"); } } } var byRefs = new List <ByReferenceResolveResult>(); List <int> refToRefs = new List <int>(); var c = 0; foreach (var binding in bindings) { var byRef = binding.CallResult as ByReferenceResolveResult; if (byRef == null) { c++; continue; } var x = byRef.ElementResult as LocalResolveResult; if (x != null && x.Variable != null && x.Variable.Type.Kind == TypeKind.ByReference) { if (binding.Parameter.IsRef || binding.Parameter.IsOut) { refToRefs.Add(c); } c++; continue; } byRefs.Add(byRef); c++; } var callArgs = bindings.Select(t => t.CallResult).ToList(); var node2 = new JInvocationExpression { Member = jsMember, Arguments = VisitExpressions(callArgs), }; foreach (var i in refToRefs) { JMemberExpression jsmex = node2.Arguments[i] as JMemberExpression; if (jsmex != null) { node2.Arguments[i] = jsmex.PreviousMember;//remove the .Value ref wrapper } } if (me != null && me.IsExtensionMethod && res.IsExtensionMethodInvocation && JMeta.ExtensionImplementedInInstance(me)) { var arg = node2.Arguments[0]; node2.Arguments.RemoveAt(0); if (jsMember.PreviousMember != null) { throw new NotImplementedException(); } jsMember.PreviousMember = arg; } TransformIntoBaseMethodCallIfNeeded(res, node2); if (att != null) { if (att.OmitParanthesis) { node2.OmitParanthesis = true; } if (node2.Arguments == null) { node2.Arguments = new List <JExpression>(); } if (att.InsertArg2 != null) { node2.Arguments.InsertOrAdd(2, new JCodeExpression { Code = att.InsertArg2.ToString() }); } if (att.InsertArg1 != null) { node2.Arguments.InsertOrAdd(1, new JCodeExpression { Code = att.InsertArg1.ToString() }); } if (att.InsertArg0 != null) { node2.Arguments.InsertOrAdd(0, new JCodeExpression { Code = att.InsertArg0.ToString() }); } node2.OmitCommas = att.OmitCommas; node2.ArgumentsPrefix = att.ArgumentsPrefix; node2.ArgumentsSuffix = att.ArgumentsSuffix; if (att.InstanceImplementedAsExtension) { var ext = (JMemberExpression)node2.Member; node2.Arguments.Insert(0, ext.PreviousMember); ext.PreviousMember = null; } } //if (me != null && me is SpecializedMethod && !Sk.IgnoreGenericMethodArguments(me)) //{ // List<JsExpression> genericArgs; // if (me.IsConstructor) // { // var ce = me.DeclaringType as ParameterizedType; // if (ce != null) // genericArgs = ce.TypeArguments.Select(t => SkJs.EntityTypeRefToMember(t, true)).ToList(); // else // genericArgs = new List<JsExpression>(); // } // else // { // var sme = (SpecializedMethod)me; // genericArgs = sme.TypeArguments.Select(t => SkJs.EntityTypeRefToMember(t, true)).ToList(); // } // if (node2.Arguments == null) // node2.Arguments = new List<JsExpression>(genericArgs); // else // node2.Arguments.InsertRange(0, genericArgs); //} if (att != null && att.OmitDotOperator) { if (node2.Member is JMemberExpression && node2.Arguments.Count == 1 && att.OmitParanthesis) { var meNode = (JMemberExpression)node2.Member; var node3 = new JBinaryExpression { Left = meNode.PreviousMember, Operator = meNode.Name, Right = node2.Arguments[0] }; return(node3); } else { Log.Warn(res.GetFirstNode(), "TODO:OmitDotOperator is not supported in this syntax."); } } if (node2.Member is JMemberExpression) { var x = (JMemberExpression)node2.Member; if (x.Name.IsNullOrEmpty() && jsMember.PreviousMember != null) { node2.Member = x.PreviousMember; } } if (res.Member.SymbolKind == SymbolKind.Indexer && JMeta.UseNativeIndexer((IProperty)res.Member)) { var node3 = new JIndexerAccessExpression { Member = node2.Member, Arguments = node2.Arguments, }; return(node3); } if (byRefs.IsNotNullOrEmpty()) { var func = J.Function(); foreach (var byRef in byRefs) { func.Add(J.Assign(VisitExpression(byRef), J.Json().Add("Value", VisitExpression(byRef))).Statement()); } func.Add(J.Var("$res", res.Type.JAccess(), node2).Statement()); foreach (var byRef in byRefs) { func.Add(J.Assign(VisitExpression(byRef), VisitExpression(byRef).Member("Value")).Statement()); } func.Add(J.Return(J.Member("$res"))); var node5 = WrapFunctionAndInvoke(res, func.Block); return(node5); } return(node2); }
public virtual TResult VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult rr, TData data) { VisitChildResolveResults(rr, data); return(default(TResult)); }
public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, IReadOnlyList <ILInstruction> callArguments, IType constrainedTo = null) { // Used for Call, CallVirt and NewObj var expectedTargetDetails = new ExpectedTargetDetails { CallOpCode = callOpCode }; TranslatedExpression target; if (callOpCode == OpCode.NewObj) { target = default(TranslatedExpression); // no target } else { target = expressionBuilder.TranslateTarget(method, callArguments.FirstOrDefault(), callOpCode == OpCode.Call, constrainedTo); if (callOpCode == OpCode.CallVirt && constrainedTo == null && target.Expression is CastExpression cast && target.ResolveResult is ConversionResolveResult conversion && target.Type.IsKnownType(KnownTypeCode.Object) && conversion.Conversion.IsBoxingConversion) { // boxing conversion on call target? // let's see if we can make that implicit: target = target.UnwrapChild(cast.Expression); // we'll need to make sure the boxing effect is preserved expectedTargetDetails.NeedsBoxingConversion = true; } } int firstParamIndex = (method.IsStatic || callOpCode == OpCode.NewObj) ? 0 : 1; // Translate arguments to the expected parameter types var arguments = new List <TranslatedExpression>(method.Parameters.Count); Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count); var expectedParameters = method.Parameters.ToList(); bool isExpandedForm = false; for (int i = 0; i < method.Parameters.Count; i++) { var parameter = expectedParameters[i]; var arg = expressionBuilder.Translate(callArguments[firstParamIndex + i]); if (parameter.IsParams && i + 1 == method.Parameters.Count) { // Parameter is marked params // If the argument is an array creation, inline all elements into the call and add missing default values. // Otherwise handle it normally. if (arg.ResolveResult is ArrayCreateResolveResult acrr && acrr.SizeArguments.Count == 1 && acrr.SizeArguments[0].IsCompileTimeConstant && acrr.SizeArguments[0].ConstantValue is int length) { var expandedParameters = expectedParameters.Take(expectedParameters.Count - 1).ToList(); var expandedArguments = new List <TranslatedExpression>(arguments); if (length > 0) { var arrayElements = ((ArrayCreateExpression)arg.Expression).Initializer.Elements.ToArray(); var elementType = ((ArrayType)acrr.Type).ElementType; for (int j = 0; j < length; j++) { expandedParameters.Add(new DefaultParameter(elementType, parameter.Name + j)); if (j < arrayElements.Length) { expandedArguments.Add(new TranslatedExpression(arrayElements[j])); } else { expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction()); } } } if (IsUnambiguousCall(expectedTargetDetails, method, target, Empty <IType> .Array, expandedArguments) == OverloadResolutionErrors.None) { isExpandedForm = true; expectedParameters = expandedParameters; arguments = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach())); continue; } } } arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true)); if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr) { dirExpr.FieldDirection = FieldDirection.Out; } } if (method is VarArgInstanceMethod) { int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount; var argListArg = new UndocumentedExpression(); argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList; int paramIndex = regularParameterCount; var builder = expressionBuilder; argListArg.Arguments.AddRange(arguments.Skip(regularParameterCount).Select(arg => arg.ConvertTo(expectedParameters[paramIndex++].Type, builder).Expression)); var argListRR = new ResolveResult(SpecialType.ArgList); arguments = arguments.Take(regularParameterCount) .Concat(new[] { argListArg.WithoutILInstruction().WithRR(argListRR) }).ToList(); method = (IMethod)method.MemberDefinition; expectedParameters = method.Parameters.ToList(); } var argumentResolveResults = arguments.Select(arg => arg.ResolveResult).ToList(); ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm); if (callOpCode == OpCode.NewObj) { if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) { var argumentExpressions = arguments.SelectArray(arg => arg.Expression); AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, expectedParameters)) { atce.Initializers.AddRange(argumentExpressions); } else { for (int i = 0; i < argumentExpressions.Length; i++) { atce.Initializers.Add( new NamedExpression { Name = expectedParameters[i].Name, Expression = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder) }); } } return(atce .WithRR(rr)); } else { if (IsUnambiguousCall(expectedTargetDetails, method, target, Empty <IType> .Array, arguments) != OverloadResolutionErrors.None) { for (int i = 0; i < arguments.Count; i++) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { if (arguments[i].Expression is LambdaExpression lambda) { ModifyReturnTypeOfLambda(lambda); } } else { arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder); } } } return(new ObjectCreateExpression(expressionBuilder.ConvertType(method.DeclaringType), arguments.SelectArray(arg => arg.Expression)) .WithRR(rr)); } } else { int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0); if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount)) { return(HandleAccessorCall(expectedTargetDetails, method, target, arguments.ToList())); } else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate) { return(new InvocationExpression(target, arguments.Select(arg => arg.Expression)).WithRR(rr)); } else if (IsDelegateEqualityComparison(method, arguments)) { return(HandleDelegateEqualityComparison(method, arguments) .WithRR(rr)); } else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) { return(HandleImplicitConversion(method, arguments[0])); } else { bool requireTypeArguments = false; bool targetCasted = false; bool argumentsCasted = false; IType[] typeArguments = Empty <IType> .Array; OverloadResolutionErrors errors; while ((errors = IsUnambiguousCall(expectedTargetDetails, method, target, typeArguments, arguments)) != OverloadResolutionErrors.None) { switch (errors) { case OverloadResolutionErrors.TypeInferenceFailed: case OverloadResolutionErrors.WrongNumberOfTypeArguments: if (requireTypeArguments) { goto default; } requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); continue; default: if (!argumentsCasted) { argumentsCasted = true; for (int i = 0; i < arguments.Count; i++) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { if (arguments[i].Expression is LambdaExpression lambda) { ModifyReturnTypeOfLambda(lambda); } } else { arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder); } } } else if (!targetCasted) { targetCasted = true; target = target.ConvertTo(method.DeclaringType, expressionBuilder); } else if (!requireTypeArguments) { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); } else { break; } continue; } break; } Expression targetExpr = target.Expression; string methodName = method.Name; // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method. if (method.IsExplicitInterfaceImplementation && targetExpr is ThisReferenceExpression) { targetExpr = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), targetExpr); methodName = method.ImplementedInterfaceMembers[0].Name; } var mre = new MemberReferenceExpression(targetExpr, methodName); if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType()))) { mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); } var argumentExpressions = arguments.Select(arg => arg.Expression); return(new InvocationExpression(mre, argumentExpressions).WithRR(rr)); } } }
public JsNode VisitInvocationResolveResult(CSharpInvocationResolveResult res) { Res = res; ProcessMember(); if (MethodAtt != null && MethodAtt.InlineCode != null) { return(Js.CodeExpression(MethodAtt.InlineCode)); } var conditional = ProcessConditional(); if (conditional) { return(null); } bool omittedCalls; var omittedCallsNode = ProcessOmitCalls(out omittedCalls); if (omittedCalls) { return(omittedCallsNode); } JsMember = SkJs.EntityToMember(Member); qiucw.CheckAddInvocation(res, JsMember.Name); ProcessTarget(); ProcessPrmBindings(); ProcessNativeParams(); ProcessByRefs1(); PrmBindings.ForEach(t => t.JsCallResult = VisitExpression(t.Binding.CallResult)); Node2 = new JsInvocationExpression { Member = JsMember, Arguments = PrmBindings.Select(t => t.JsCallResult).ToList(), }; ProcessByRefs2(); ProcessExtensionImplementedInInstance(); TransformIntoBaseMethodCallIfNeeded(Res, Node2); ProcessArgsCustomization(); ProcessGenericMethodArgs(); var inlineCodeExpression = ProcessInlineCodeExpression(); if (inlineCodeExpression != null) { return(inlineCodeExpression); } var omittedDotOperator = ProcessOmitDotOperator(); if (omittedDotOperator != null) { return(omittedDotOperator); } ProcessRemoveEmptyPreviousMemberName(); var indexerAccess = ProcessIndexer(); if (indexerAccess != null) { return(indexerAccess); } ProcessByRefs3(); return(Node2); }
private JNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res) { if (res.Type.Kind == TypeKind.Delegate) { return(Visit(res.Arguments.Single())); } var me = (IMethod)res.Member; var meAtt = JMeta.GetJMethodAttribute(me); var ce = me.GetDeclaringTypeDefinition(); var att = ce == null ? null : ce.GetJsTypeAttribute(); if (att != null && att.Mode == JsMode.Json && (meAtt == null || meAtt.Name == null)) { var node2 = VisitInvocationResolveResult(res); var json = InitializersToJson(res.InitializerStatements, res.Type); return(json); } else { var invokeExp = (JInvocationExpression)VisitInvocationResolveResult(res); var newExp = new JNewObjectExpression { Invocation = invokeExp }; JExpression finalExp; if (meAtt != null && meAtt.OmitNewOperator) { finalExp = invokeExp; } else { finalExp = newExp; } if (meAtt != null && meAtt.JsonInitializers) { var json = InitializersToJson(res.InitializerStatements, res.Type); invokeExp.Arguments.Add(json); } else if (res.InitializerStatements.IsNotNullOrEmpty()) { //var func = J.Function(); var func = J.Block(); var inits2 = res.InitializerStatements.Select(t => Visit(t)).ToList(); var init1 = res.InitializerStatements[0]; var target = FindInitializedObjectResolveResult(res);// ((init1 as OperatorResolveResult).Operands[0] as MemberResolveResult).TargetResult as InitializedObjectResolveResult; var varName = Initializers[target]; func.Add(J.Var(varName, res.Type.JAccess(), finalExp).Statement()); foreach (var init in inits2) { var exp = ((JExpression)init); func.Add(exp.Statement()); } func.Add(J.Return(J.Member(varName))); finalExp = WrapFunctionAndInvoke(res, func); } return(finalExp); } }
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.Emitter.IsInlineConst(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.Emitter.IsInlineConst(member.Member)) { 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); } }
public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression, out Expression formatArgument, out IList <Expression> arguments, Func <IParameter, Expression, bool> argumentFilter) { if (argumentFilter == null) { argumentFilter = (p, e) => true; } formatArgument = null; arguments = new List <Expression>(); // Serach for method of type: void Name(string format, params object[] args); if (invocationResolveResult.Member.SymbolKind == SymbolKind.Method && invocationResolveResult.Member.DeclaringType != null) { var methods = invocationResolveResult.Member.DeclaringType.GetMethods(m => m.Name == invocationResolveResult.Member.Name).ToList(); if (!methods.Any(m => m.Parameters.Count == 2 && m.Parameters[0].Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(m.Parameters[0].Name) && m.Parameters[1].IsParams)) { return(false); } } var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap(); var resolvedParameters = invocationResolveResult.Member.Parameters; var allArguments = invocationExpression.Arguments.ToArray(); for (int i = 0; i < allArguments.Length; i++) { var parameterIndex = argumentToParameterMap[i]; if (parameterIndex < 0 || parameterIndex >= resolvedParameters.Count) { // No valid mapping for this argument, skip it continue; } var parameter = resolvedParameters[parameterIndex]; var argument = allArguments[i]; if (i == 0 && parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name)) { formatArgument = argument; } else if (formatArgument != null && parameter.IsParams && !invocationResolveResult.IsExpandedForm) { if (!(argument is ArrayCreateExpression ace) || ace.Initializer.IsNull) { return(false); } foreach (var element in ace.Initializer.Elements) { if (argumentFilter(parameter, element)) { arguments.Add(argument); } } } else if (formatArgument != null && argumentFilter(parameter, argument)) { arguments.Add(argument); } } return(formatArgument != null); }
public override void VisitInvocationExpression(InvocationExpression invocationExpression) { base.VisitInvocationExpression(invocationExpression); var method = invocationExpression.GetSymbol() as IMethod; if (method == null || !method.IsExtensionMethod || !invocationExpression.Arguments.Any()) { return; } IReadOnlyList <IType> typeArguments; MemberReferenceExpression memberRefExpr; switch (invocationExpression.Target) { case MemberReferenceExpression mre: typeArguments = mre.TypeArguments.Any() ? method.TypeArguments : EmptyList <IType> .Instance; memberRefExpr = mre; break; case IdentifierExpression ide: typeArguments = ide.TypeArguments.Any() ? method.TypeArguments : EmptyList <IType> .Instance; memberRefExpr = null; break; default: return; } var firstArgument = invocationExpression.Arguments.First(); if (firstArgument is NamedArgumentExpression) { return; } var target = firstArgument.GetResolveResult(); if (target is ConstantResolveResult crr && crr.ConstantValue == null) { target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); } ResolveResult[] args = new ResolveResult[invocationExpression.Arguments.Count - 1]; string[] argNames = null; int pos = 0; foreach (var arg in invocationExpression.Arguments.Skip(1)) { if (arg is NamedArgumentExpression nae) { if (argNames == null) { argNames = new string[args.Length]; } argNames[pos] = nae.Name; args[pos] = nae.Expression.GetResolveResult(); } else { args[pos] = arg.GetResolveResult(); } pos++; } if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames)) { return; } if (firstArgument is DirectionExpression dirExpr) { if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out) { return; } firstArgument = dirExpr.Expression; target = firstArgument.GetResolveResult(); dirExpr.Detach(); } else if (firstArgument is NullReferenceExpression) { Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace)); firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach())); } if (invocationExpression.Target is IdentifierExpression identifierExpression) { identifierExpression.Detach(); memberRefExpr = new MemberReferenceExpression(firstArgument.Detach(), method.Name, identifierExpression.TypeArguments.Detach()); invocationExpression.Target = memberRefExpr; } else { memberRefExpr.Target = firstArgument.Detach(); } if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr) { // do not forget to update the CSharpInvocationResolveResult => set IsExtensionMethodInvocation == true invocationExpression.RemoveAnnotations <CSharpInvocationResolveResult>(); var newResolveResult = new CSharpInvocationResolveResult( irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors, isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation, irr.GetArgumentToParameterMap(), irr.InitializerStatements); invocationExpression.AddAnnotation(newResolveResult); } }
public JsNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res) { if (res.Type.Kind == TypeKind.Delegate) { return(Visit(res.Arguments.Single())); } var me = (IMethod)res.Member; var meAtt = Sk.GetJsMethodAttribute(me); var ce = me.GetDeclaringTypeDefinition(); var att = ce == null ? null : ce.GetJsTypeAttribute(); if (att != null && att.Mode == JsMode.Json && (meAtt == null || meAtt.Name == null)) { var jtfn = ce == null ? null : Sk.GetJsonTypeFieldName(ce); var node2 = VisitInvocationResolveResult(res); var json = Importer.InitializersToJson(res.InitializerStatements, res.Type); if (jtfn != null) { var x = json as JsJsonObjectExpression; if (x != null) { x.Add(jtfn, SkJs.EntityTypeRefToMember(res.Type)); } } return(json); } else { var invokeExp = (JsInvocationExpression)VisitInvocationResolveResult(res); var newExp = new JsNewObjectExpression { Invocation = invokeExp }; JsExpression finalExp; if (meAtt != null && meAtt.OmitNewOperator) { finalExp = invokeExp; } else { finalExp = newExp; } if (meAtt != null && meAtt.JsonInitializers) { var json = Importer.InitializersToJson(res.InitializerStatements, res.Type); invokeExp.Arguments.Add(json); } else if (res.InitializerStatements.IsNotNullOrEmpty()) { var func = Js.Function(); var inits2 = res.InitializerStatements.Select(t => Visit(t)).ToList(); //var init1 = res.InitializerStatements[0]; var target = AstNodeConverter.FindInitializedObjectResolveResult(res);// ((init1 as OperatorResolveResult).Operands[0] as MemberResolveResult).TargetResult as InitializedObjectResolveResult; var varName = Importer.Initializers[target]; func.Add(Js.Var(varName, finalExp).Statement()); foreach (var init in inits2) { var exp = ((JsExpression)init); func.Add(exp.Statement()); } func.Add(Js.Return(Js.Member(varName))); finalExp = Importer.WrapFunctionAndInvoke(res, func); } return(finalExp); } }
void TransformIntoBaseMethodCallIfNeeded(CSharpInvocationResolveResult res, JsInvocationExpression node2) { var target = res.TargetResult as ThisResolveResult; if (target != null && target.CausesNonVirtualInvocation) //base. { //var info = res.GetInfo(); //var node = info.Nodes.FirstOrDefault(); var ce = target.Type;// node.FindThisEntity(); if (ce != null && Sk.IsExtJsType(ce.GetDefinitionOrArrayType())) { node2.Member = Js.This().Member("callParent"); if (node2.Arguments.IsNotNullOrEmpty()) { node2.Arguments = new List <JsExpression> { Js.NewJsonArray(node2.Arguments.ToArray()) } } ; //var me2 = (node2.Member as JsMemberExpression); //me2.Name = "callParent"; return; } IMethod me2; var me = res.Member; if (me is IProperty) { me2 = ((IProperty)me).Getter; } else if (me is IMethod) { me2 = (IMethod)res.Member; } else { throw new Exception("Can't resolve method from member: " + res.Member); } var member = SkJs.EntityMethodToJsFunctionRef(me2); member = member.Member("call"); node2.Member = member; if (node2.Arguments == null) { node2.Arguments = new List <JsExpression>(); } node2.Arguments.Insert(0, Js.This()); } } void ProcessByRefs1() { ByRefs = new List <ByReferenceResolveResult>(); ByRefIndexes = new List <int>(); RefToRefs = new List <int>(); var c = 0; foreach (var bin in PrmBindings) { var binding = bin.Binding; var byRef = binding.CallResult as ByReferenceResolveResult; if (byRef == null) { c++; continue; } var x = byRef.ElementResult as LocalResolveResult; if (x != null && x.Variable != null && x.Variable.Type.Kind == TypeKind.ByReference) { if (binding.Parameter.IsRef || binding.Parameter.IsOut) { RefToRefs.Add(c); } c++; continue; } ByRefs.Add(byRef); ByRefIndexes.Add(c); c++; } } void ProcessByRefs2() { var c = 0; for (var i = 0; i < Node2.Arguments.Count; i++) { if (Node2.Arguments[i] is JsMemberExpression) { JsMemberExpression jsmex = Node2.Arguments[i] as JsMemberExpression; if (RefToRefs.Contains(i)) { Node2.Arguments[i] = jsmex.PreviousMember; //remove the .Value ref wrapper } else if (ByRefIndexes.Contains(i)) { Node2.Arguments[i] = Js.Member(RefIndexToName(c)); c++; } } else if (Node2.Arguments[i] is JsIndexerAccessExpression) { if (ByRefIndexes.Contains(i)) { Node2.Arguments[i] = Js.Member(RefIndexToName(c)); c++; } } } } void ProcessByRefs3() { if (ByRefs.IsNotNullOrEmpty()) { var func = Js.Function(); //It must assigned to a temporary variable, because typed arrays do not acceppt json. //调整原来使用临时对象.Value的赋值方式,修改为Object.defineProperty定义get|set方法的实现 //临时对象统一调用jsclr里的$Ref方法进行创建 for (var i = 0; i < ByRefs.Count; i++) { var byRef = ByRefs[i]; var expr = VisitExpression(byRef); if (expr is JsMemberExpression) { var memberExpr = expr as JsMemberExpression; if (memberExpr.PreviousMember != null) { var refFuncInvoke = new JsInvocationExpression { Member = new JsMemberExpression { Name = "$Ref" }, Arguments = new List <JsExpression> { memberExpr.PreviousMember, Js.String(memberExpr.Name) } }; func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement()); } else { //如果是局部变量的话使用旧实现方式 var refFuncInvoke = new JsInvocationExpression { Member = new JsMemberExpression { Name = "$Ref" }, Arguments = new List <JsExpression> { Js.Member("null"), memberExpr } }; func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement()); } } else if (expr is JsIndexerAccessExpression) { var indexerExpr = expr as JsIndexerAccessExpression; var indexArg = indexerExpr.Arguments[0]; var refFuncInvoke = new JsInvocationExpression { Member = new JsMemberExpression { Name = "$Ref" }, Arguments = new List <JsExpression> { indexerExpr.Member, indexArg } }; func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement()); } } func.Add(Js.Var("$res", Node2).Statement()); for (var i = 0; i < ByRefs.Count; i++) { var byRef = ByRefs[i]; var memberExpr = VisitExpression(byRef) as JsMemberExpression; if (memberExpr != null && memberExpr.PreviousMember == null) { func.Add(memberExpr.Assign(Js.Member(RefIndexToName(i)).Member("Value")).Statement()); } } func.Add(Js.Return(Js.Member("$res"))); Node2 = Importer.WrapFunctionAndInvoke(Res, func); } }
public JNode VisitOperatorResolveResult(OperatorResolveResult res) { if (res.Operands.Count == 1) { if (res.UserDefinedOperatorMethod != null && !JMeta.UseNativeOperatorOverloads(res.UserDefinedOperatorMethod.DeclaringTypeDefinition)) { var fake = Cs.InvokeMethod(res.UserDefinedOperatorMethod, null, res.Operands[0]); return(Visit(fake)); } var isProperty = false; var meRes = res.Operands[0] as MemberResolveResult; if (meRes != null && meRes.Member != null && IsEntityFunctionProperty(meRes.Member, res)) { isProperty = true; } JExpression node2; if (res.OperatorType == System.Linq.Expressions.ExpressionType.Negate || res.OperatorType == System.Linq.Expressions.ExpressionType.PreDecrementAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.PreIncrementAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.Not || res.OperatorType == System.Linq.Expressions.ExpressionType.OnesComplement) { var simpler = res.OperatorType.ExtractCompoundAssignment(); if (isProperty && simpler != null) { var fakeCs = meRes.Member.AccessSelf().Binary(simpler.Value, Cs.Value(1, Project), meRes.Type); node2 = VisitExpression(fakeCs); } else { node2 = new JPreUnaryExpression { Operator = Visit(res.OperatorType), Right = VisitExpression(res.Operands[0]) }; } } else if (res.OperatorType == System.Linq.Expressions.ExpressionType.PostIncrementAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.PostDecrementAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.PreIncrementAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.PreDecrementAssign) { if (isProperty) { var simpler = res.OperatorType.ExtractCompoundAssignment(); var fakeCs = meRes.Member.AccessSelf().Binary(simpler.Value, Cs.Value(1, Project), meRes.Type); node2 = VisitExpression(fakeCs); } else { node2 = new JPostUnaryExpression { Operator = Visit(res.OperatorType), Left = VisitExpression(res.Operands[0]) }; } } else { throw new NotImplementedException(); } return(node2); } else if (res.Operands.Count == 2) { if (res.UserDefinedOperatorMethod != null && !JMeta.UseNativeOperatorOverloads(res.UserDefinedOperatorMethod.DeclaringTypeDefinition)) { var fake = Cs.InvokeMethod(res.UserDefinedOperatorMethod, null, res.Operands[0], res.Operands[1]); return(Visit(fake)); } if (res.OperatorType == System.Linq.Expressions.ExpressionType.Coalesce) { var fake = Cs.Conditional(res.Operands[0].NotEqual(Cs.Null(), Project), res.Operands[0], res.Operands[1], res.Type); var fake2 = Visit(fake); fake2 = new JParenthesizedExpression { Expression = (JExpression)fake2 }; return(fake2); } var mrrOp0 = res.Operands[0] as MemberResolveResult; if (mrrOp0 != null && mrrOp0.Member.SymbolKind == SymbolKind.Event) { var pe = (IEvent)mrrOp0.Member; if (res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.SubtractAssign) { var accessor = res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign ? pe.AddAccessor : pe.RemoveAccessor; var fake = new CSharpInvocationResolveResult(mrrOp0.TargetResult, accessor, new List <ResolveResult> { res.Operands[1] }); var node6 = Visit(fake); return(node6); } } if (mrrOp0 != null && IsEntityFunctionProperty(mrrOp0.Member, res)) { var compOpType = res.OperatorType.ExtractCompoundAssignment(); var pe = (IProperty)mrrOp0.Member; if (compOpType != null) { var fake = new CSharpInvocationResolveResult(mrrOp0.TargetResult, pe.Setter, new List <ResolveResult> { new OperatorResolveResult(res.Type, compOpType.Value, new CSharpInvocationResolveResult(mrrOp0.TargetResult, pe.Getter, null), res.Operands[1]) }); var node6 = Visit(fake); return(node6); } else if (res.OperatorType == System.Linq.Expressions.ExpressionType.Assign) { var args = new List <ResolveResult>(); if (pe.IsIndexer) { var irrOp0 = (CSharpInvocationResolveResult)res.Operands[0]; args.AddRange(irrOp0.Arguments); } args.Add(res.Operands[1]); var fake = new CSharpInvocationResolveResult(mrrOp0.TargetResult, pe.Setter, args).AssociateWithOriginal(res); var node6 = Visit(fake); node6 = WrapSetterToReturnValueIfNeeded(res, node6); return(node6); } } if (res.Operands[0] is ConversionResolveResult && res.Operands[1] is ConstantResolveResult) { var leftConv = (ConversionResolveResult)res.Operands[0]; var rightConst = (ConstantResolveResult)res.Operands[1]; if (leftConv.Conversion.IsNumericConversion && leftConv.Input.Type == Cs.CharType(Project)) { var value = ((char)(int)rightConst.ConstantValue).ToString(); var fake = Cs.Binary(leftConv.Input, res.OperatorType, Cs.Value(value, Project), leftConv.Input.Type); return(Visit(fake)); } } if (res.Operands[0].Type.Kind == TypeKind.Delegate && res.Operands[1].Type.Kind == TypeKind.Delegate) { if (res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.SubtractAssign) { var op = res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign ? System.Linq.Expressions.ExpressionType.Add : System.Linq.Expressions.ExpressionType.Subtract; var fake = Cs.Assign(res.Operands[0], Cs.Binary(res.Operands[0], op, res.Operands[1], res.Type)); var node6 = Visit(fake); return(node6); } else if (res.OperatorType == System.Linq.Expressions.ExpressionType.Add || res.OperatorType == System.Linq.Expressions.ExpressionType.Subtract) { var combineMethod = Compiler.Project.Compilation.FindType(KnownTypeCode.Delegate).GetMethods(t => t.Name == "Combine").FirstOrDefault(); var removeMethod = Compiler.Project.Compilation.FindType(KnownTypeCode.Delegate).GetMethods(t => t.Name == "Remove").FirstOrDefault(); var meOp = res.OperatorType == System.Linq.Expressions.ExpressionType.Add ? combineMethod : removeMethod; var fake = Cs.Member(null, meOp).Invoke(res.Operands[0], res.Operands[1]); var node6 = Visit(fake); return(node6); } } var node5 = new JBinaryExpression { Operator = Visit(res.OperatorType), Left = VisitExpression(res.Operands[0]), Right = VisitExpression(res.Operands[1]) }; if (res.OperatorType == System.Linq.Expressions.ExpressionType.Equal && node5.Operator == "==") { var att = JMeta.GetJsExportAttribute(Project.Compilation.MainAssembly); if (att != null && att.UseExactEquals) { node5.Operator = "==="; } } if (res.OperatorType == System.Linq.Expressions.ExpressionType.NotEqual && node5.Operator == "!=") { var att = JMeta.GetJsExportAttribute(Project.Compilation.MainAssembly); if (att != null && att.UseExactEquals) { node5.Operator = "!=="; } } return(node5); } else if (res.Operands.Count == 3) { if (res.OperatorType == System.Linq.Expressions.ExpressionType.Conditional) { var node5 = new JConditionalExpression { Condition = VisitExpression(res.Operands[0]), TrueExpression = VisitExpression(res.Operands[1]), FalseExpression = VisitExpression(res.Operands[2]) }; return(node5); } else { throw new NotImplementedException(); } } else { throw new NotImplementedException(); } }
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 method = (IMethod)member.Member; if (method.TypeArguments.Count > 0) { 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.ROOT || !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}"); } 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 == "(" ) ) { 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; } else { 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)) { 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 { this.Write(this.Emitter.GetEntityName(member.Member)); } } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
public virtual object VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult rr, object data) { VisitChildResolveResults(rr, data); return(null); }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; /*if (identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression)) * { * resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter); * expressionResolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); * } * else * { * resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); * }*/ 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; } IMemberDefinition member = this.ResolveFieldOrMethod(id, identifierExpression.TypeArguments.Count); if (member == null && memberResult != null) { var iMethod = memberResult.Member as IMethod; if (iMethod != null) { member = this.ResolveFieldOrMethod(id, iMethod.TypeParameters.Count); } } if (member != null) { MethodDefinition method = member as MethodDefinition; FieldDefinition field = member as FieldDefinition; bool isStatic = method != null && method.IsStatic || field != null && field.IsStatic; string appendAdditionalCode = null; if (method != null) { string inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { return; } 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; 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 = ")"; } } } bool isConst = false; bool isInlineConst = false; if (memberResult != null) { isConst = this.Emitter.IsMemberConst(memberResult.Member); if (isConst) { isInlineConst = this.Emitter.IsInlineConst(memberResult.Member); } } if (!(resolveResult is TypeResolveResult) && !isInlineConst) { if (isStatic) { if (memberResult != null) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); } else { this.Write(BridgeTypes.ToJsName(member.DeclaringType, this.Emitter)); } } else { this.WriteThis(); } this.WriteDot(); } if (method != null) { 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 (resolveResult is MemberResolveResult) { MemberResolveResult memberResolveResult = (MemberResolveResult)resolveResult; this.Write(OverloadsCollection.Create(this.Emitter, memberResolveResult.Member).GetOverloadName()); } else { this.Write(this.Emitter.GetDefinitionName(method)); } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } } else if (memberResult != null) { if (isInlineConst) { this.WriteScript(memberResult.ConstantValue); } else if (memberResult != null && memberResult.Member is DefaultResolvedEvent && 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, memberResult.Member).GetOverloadName()); this.WriteOpenParentheses(); } 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 { this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName()); } } } else if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(((TypeResolveResult)resolveResult).Type, this.Emitter)); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this); return; } if (resolveResult is TypeResolveResult) { this.Write(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) { 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); } } else 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 && 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 { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is TypeResolveResult) { var typeResolveResult = (TypeResolveResult)resolveResult; 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(); } } else if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member)); } else { this.Write(resolveResult.ToString()); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this); } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } }
public override string VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult rr, object data) { return(VisitInvocationResolveResult(rr, data)); }