private object GetConstValue(OperatorResolveResult orr, bool isLeft, bool isChar) { var result = isLeft ? orr.Operands.First() : orr.Operands.Last(); if (result.IsCompileTimeConstant) { return(WrapConstValue(result.ConstantValue)); } ConversionResolveResult rr = result as ConversionResolveResult; if (rr != null && rr.Input.IsCompileTimeConstant) { if (isChar) { return(isLeft ? this.BinaryOperatorExpression.Left.ToString() : this.BinaryOperatorExpression.Right.ToString()); } else if (rr.Input.Type.Kind == TypeKind.Enum) { MemberResolveResult reslut = (MemberResolveResult)rr.Input; return("\"" + reslut.Member.Name + "\""); } return(WrapConstValue(rr.Input.ConstantValue)); } return(null); }
public JsNode VisitConversionResolveResult(ConversionResolveResult res) { var input = res.Input; var conversion = res.Conversion; var conversionType = res.Type; var info = res.GetInfo(); if (info == null) { info = new ResolveResultInfo { Conversion = conversion, ResolveResult = res, ConversionTargetType = res.Type }; res.SetInfo(info); } var info2 = input.GetInfo(); if (info2 == null) { input.SetInfo(new ResolveResultInfo { Nodes = info.Nodes.ToList(), Conversion = conversion, ConversionTargetType = res.Type, ResolveResult = input }); } if (conversion.IsUserDefined && res.Type.FullName == "SharpKit.JavaScript.JsCode" && input is ConstantResolveResult) { var value = ((ConstantResolveResult)input).ConstantValue; var node3 = Js.CodeExpression(value == null ? "null" : value.ToString()); return(node3); } return(VisitConversion(input, conversion, conversionType)); }
public IList<ResolveResult> GetArgumentsWithConversions() { if (bestCandidate == null) return arguments; var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { if (conversions[i] == Conversion.IdentityConversion) { args[i] = arguments[i]; } else { int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; IType parameterType; if (parameterIndex >= 0) { parameterType = bestCandidate.ParameterTypes[parameterIndex]; } else { parameterType = SpecialType.UnknownType; } if (arguments[i].IsCompileTimeConstant && conversions[i] != Conversion.None) { args[i] = new CppResolver(compilation).ResolveCast(parameterType, arguments[i]); } else { args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]); } } } return args; }
Value Visit(ConversionResolveResult result) { if (result.IsError) { throw new GetValueException("Cannot convert from '{0}' to '{1}'.", new CSharpAmbience().ConvertType(result.Input.Type), new CSharpAmbience().ConvertType(result.Type)); } var val = Convert(result.Input); if (result.Conversion.IsBoxingConversion) { return(val); } if (result.Conversion.IsIdentityConversion) { return(val); } if (result.Conversion.IsNumericConversion) { var convVal = CSharpPrimitiveCast.Cast(ReflectionHelper.GetTypeCode(result.Type), val.PrimitiveValue, false); return(Eval.CreateValue(evalThread, convVal)); } if (result.Conversion.IsUserDefined) { return(InvokeMethod(null, result.Conversion.Method, val)); } if (result.Conversion.IsReferenceConversion && result.Conversion.IsImplicit) { return(val); } if (result.Conversion.IsNullLiteralConversion) { return(val); } throw new GetValueException("conversion '{0}' not implemented!", result.Conversion); }
public void ParamsAttribute_String() { ConversionResolveResult rr = (ConversionResolveResult)GetParamsAttributeArgument(4); Assert.AreEqual("System.Object", rr.Type.FullName); Assert.AreEqual("System.String", rr.Input.Type.FullName); Assert.AreEqual("Test", rr.Input.ConstantValue); }
ResolveResult Unbox(ResolveResult resolveResult) { ConversionResolveResult crr = (ConversionResolveResult)resolveResult; Assert.AreEqual(TypeKind.Class, crr.Type.Kind); Assert.AreEqual("System.Object", crr.Type.FullName); Assert.AreEqual(Conversion.BoxingConversion, crr.Conversion); return(crr.Input); }
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(); var target = firstArgument.GetResolveResult(); if (target is ConstantResolveResult crr && crr.ConstantValue == null) { target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); } var args = invocationExpression.Arguments.Skip(1).Select(a => a.GetResolveResult()).ToArray(); if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args)) { return; } if (firstArgument is NullReferenceExpression) { 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(); } }
public JsNode VisitConversionResolveResult(ConversionResolveResult res) { var input = res.Input; var conversion = res.Conversion; var conversionType = res.Type; var info = res.GetInfo(); if (info == null) { info = new ResolveResultInfo { Conversion = conversion, ResolveResult = res, ConversionTargetType = res.Type }; res.SetInfo(info); } var info2 = input.GetInfo(); if (info2 == null) { input.SetInfo(new ResolveResultInfo { Nodes = info.Nodes.ToList(), Conversion = conversion, ConversionTargetType = res.Type, ResolveResult = input }); } if (conversion.IsUserDefined && res.Type.FullName == "SharpKit.JavaScript.JsCode" && input is ConstantResolveResult) { var value = ((ConstantResolveResult)input).ConstantValue; var node3 = Js.CodeExpression(value == null ? "null" : value.ToString()); return(node3); } #region 修复c#方法重载导致转js后绑定错误 var tInfo = input.Tag as ResolveResultInfo; if (tInfo != null && tInfo.Conversion != null && tInfo.Conversion.Method != null && conversion != null && conversion.Method != null) { if (tInfo.Conversion.Method.ToString() != conversion.Method.ToString()) { //var tMessage = string.Format("方法绑定异常:绑定了错误的方法:{0}\n正确的绑定应该是:{1}", tInfo.Conversion.Method.ToString(), conversion.Method.ToString()); //Log.Error(tMessage); //处理方法绑定异常 var tNewTag = res.Tag as ResolveResultInfo; var tTag = input.Tag as ResolveResultInfo; tTag.Conversion = tNewTag.Conversion; tTag.ConversionTargetType = tNewTag.ConversionTargetType; tTag.ResolveResult = tNewTag.ResolveResult; } } #endregion return(VisitConversion(input, conversion, conversionType)); }
IList <ResolveResult> GetArgumentsWithConversions(ResolveResult targetResolveResult, IParameterizedMember bestCandidateForNamedArguments) { var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { var argument = arguments[i]; if (this.IsExtensionMethodInvocation && i == 0 && targetResolveResult != null) { argument = targetResolveResult; } int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; if (parameterIndex >= 0 && conversions[i] != Conversion.IdentityConversion) { // Wrap argument in ConversionResolveResult IType parameterType = bestCandidate.ParameterTypes[parameterIndex]; if (parameterType.Kind != TypeKind.Unknown) { if (arguments[i].IsCompileTimeConstant && conversions[i].IsValid && !conversions[i].IsUserDefined) { argument = new CSharpResolver(compilation).WithCheckForOverflow(CheckForOverflow).ResolveCast(parameterType, argument); } else { argument = new ConversionResolveResult(parameterType, argument, conversions[i], CheckForOverflow); } } } if (bestCandidateForNamedArguments != null && argumentNames[i] != null) { // Wrap argument in NamedArgumentResolveResult if (parameterIndex >= 0) { argument = new NamedArgumentResolveResult(bestCandidateForNamedArguments.Parameters[parameterIndex], argument, bestCandidateForNamedArguments); } else { argument = new NamedArgumentResolveResult(argumentNames[i], argument); } } args[i] = argument; } return(args); }
public override JsExpression VisitConversionResolveResult(ConversionResolveResult rr, object data) { var input = VisitResolveResult(rr.Input, null); if (rr.Conversion.IsIdentityConversion) { return input; } else if (rr.Conversion.IsAnonymousFunctionConversion) { var result = input; if (rr.Type.Name == "Expression") result = CompileFactoryCall("Quote", new[] { typeof(Expression) }, new[] { result }); return result; } else if (rr.Conversion.IsNullLiteralConversion) { return CompileFactoryCall("Constant", new[] { typeof(object), typeof(Type) }, new[] { input, _instantiateType(rr.Type) }); } else if (rr.Conversion.IsMethodGroupConversion) { var methodInfo = _compilation.FindType(typeof(MethodInfo)); return CompileFactoryCall("Convert", new[] { typeof(Expression), typeof(Type) }, new[] { CompileFactoryCall("Call", new[] { typeof(Expression), typeof(MethodInfo), typeof(Expression[]) }, new[] { CompileFactoryCall("Constant", new[] { typeof(object), typeof(Type) }, new[] { _getMember(rr.Conversion.Method), _instantiateType(methodInfo) }), _getMember(methodInfo.GetMethods().Single(m => m.Name == "CreateDelegate" && m.Parameters.Count == 2 && m.Parameters[0].Type.FullName == typeof(Type).FullName && m.Parameters[1].Type.FullName == typeof(object).FullName)), JsExpression.ArrayLiteral( _instantiateType(rr.Type), rr.Conversion.Method.IsStatic ? JsExpression.Null : VisitResolveResult(((MethodGroupResolveResult)rr.Input).TargetResult, null) ) }), _instantiateType(rr.Type) }); } else { string methodName; if (rr.Conversion.IsTryCast) methodName = "TypeAs"; else if (rr.CheckForOverflow) methodName = "ConvertChecked"; else methodName = "Convert"; if (rr.Conversion.IsUserDefined) return CompileFactoryCall(methodName, new[] { typeof(Expression), typeof(Type), typeof(MethodInfo) }, new[] { input, _instantiateType(rr.Type), _getMember(rr.Conversion.Method) }); else return CompileFactoryCall(methodName, new[] { typeof(Expression), typeof(Type) }, new[] { input, _instantiateType(rr.Type) }); } }
static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, InvocationExpression invocationExpression, out MemberReferenceExpression memberRefExpr, out ResolveResult target, out Expression firstArgument) { var method = invocationExpression.GetSymbol() as IMethod; memberRefExpr = null; target = null; firstArgument = null; if (method == null || !method.IsExtensionMethod || !invocationExpression.Arguments.Any()) { return(false); } IReadOnlyList <IType> typeArguments; 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(false); } firstArgument = invocationExpression.Arguments.First(); if (firstArgument is NamedArgumentExpression) { return(false); } target = firstArgument.GetResolveResult(); if (target is ConstantResolveResult crr && crr.ConstantValue == null) { target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); }
public virtual TResult VisitConversionResolveResult(ConversionResolveResult rr, TData data) { VisitChildResolveResults(rr, data); return(default(TResult)); }
public ImplicitConversionAnnotation(ConversionResolveResult conversionResolveResult) { this.ConversionResolveResult = conversionResolveResult; }
IList<ResolveResult> GetArgumentsWithConversions(ResolveResult targetResolveResult, IParameterizedMember bestCandidateForNamedArguments) { var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { var argument = arguments[i]; if (this.IsExtensionMethodInvocation && i == 0 && targetResolveResult != null) argument = targetResolveResult; int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; if (parameterIndex >= 0 && conversions[i] != Conversion.IdentityConversion) { // Wrap argument in ConversionResolveResult IType parameterType = bestCandidate.ParameterTypes[parameterIndex]; if (parameterType.Kind != TypeKind.Unknown) { if (arguments[i].IsCompileTimeConstant && conversions[i] != Conversion.None) { argument = new CSharpResolver(compilation).WithCheckForOverflow(CheckForOverflow).ResolveCast(parameterType, argument); } else { argument = new ConversionResolveResult(parameterType, argument, conversions[i], CheckForOverflow); } } } if (bestCandidateForNamedArguments != null && argumentNames[i] != null) { // Wrap argument in NamedArgumentResolveResult if (parameterIndex >= 0) { argument = new NamedArgumentResolveResult(bestCandidateForNamedArguments.Parameters[parameterIndex], argument, bestCandidateForNamedArguments); } else { argument = new NamedArgumentResolveResult(argumentNames[i], argument); } } args[i] = argument; } return args; }
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 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(); } }
// The reason this class exists is that for code like this: // int i = ...; // long n = 0; // n = n + (long)i; // The resolver will produce (and process) an CastResolveResult for the cast, // (with Conversion = implicit numeric conversion) // and then pass it into CSharpResolver.ResolveBinaryOperator(). // That method normally wraps input arguments into another conversion // (the implicit conversion applied by the operator). // However, identity conversions do not cause the creation of ConversionResolveResult instances, // so the OperatorResolveResult's argument will be the CastResolveResult // of the cast. // Without this class (and instead using ConversionResolveResult for both purposes), // it would be hard for the conversion-processing code // in the ResolveVisitor to distinguish the existing conversion from the CastExpression // from an implicit conversion introduced by the binary operator. // This would cause the conversion to be processed yet again. // The following unit tests would fail without this class: // * CastTests.ExplicitConversion_In_Assignment // * FindReferencesTest.FindReferencesForOpImplicitInAssignment_ExplicitCast // * CS0029InvalidConversionIssueTests.ExplicitConversionFromUnknownType public CastResolveResult(ConversionResolveResult rr) : base(rr.Type, rr.Input, rr.Conversion, rr.CheckForOverflow) { }
public virtual object VisitConversionResolveResult(ConversionResolveResult rr, object data) { VisitChildResolveResults(rr, data); return(null); }
private ResolveResult ResolveWithConversion(Expression expr) { var rr = _resolver.Resolve(expr); var conversion = _resolver.GetConversion(expr); if (!conversion.IsIdentityConversion) rr = new ConversionResolveResult(_resolver.GetExpectedType(expr), rr, conversion); return rr; }
IList<ResolveResult> GetArgumentsWithConversions(ResolveResult targetResolveResult) { var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { var argument = arguments[i]; if (this.IsExtensionMethodInvocation && i == 0 && targetResolveResult != null) argument = targetResolveResult; if (conversions[i] == Conversion.IdentityConversion) { args[i] = argument; } else { int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; IType parameterType; if (parameterIndex >= 0) { parameterType = bestCandidate.ParameterTypes[parameterIndex]; } else { parameterType = SpecialType.UnknownType; } if (arguments[i].IsCompileTimeConstant && conversions[i] != Conversion.None) { args[i] = new CSharpResolver(compilation).ResolveCast(parameterType, argument); } else { args[i] = new ConversionResolveResult(parameterType, argument, conversions[i]); } } } return args; }
public override string VisitConversionResolveResult(ConversionResolveResult rr, object data) { var input = VisitResolveResult(rr.Input, null); if (rr.Conversion.IsIdentityConversion) { return(input); } else if (rr.Conversion.IsAnonymousFunctionConversion) { var result = input; if (rr.Type.Name == "Expression") { result = CompileFactoryCall("Quote", new[] { typeof(Expression) }, new[] { result }); } return(result); } else if (rr.Conversion.IsNullLiteralConversion) { return(CompileFactoryCall("Constant", new[] { typeof(object), typeof(Type) }, new[] { input, ExpressionTreeBuilder.GetTypeName(rr.Type, this._emitter) })); } else if (rr.Conversion.IsMethodGroupConversion) { var methodInfo = _compilation.FindType(typeof(MethodInfo)); return(CompileFactoryCall("Convert", new[] { typeof(Expression), typeof(Type) }, new[] { CompileFactoryCall("Call", new[] { typeof(Expression), typeof(MethodInfo), typeof(Expression[]) }, new[] { CompileFactoryCall("Constant", new[] { typeof(object), typeof(Type) }, new[] { this.GetMember(rr.Conversion.Method), ExpressionTreeBuilder.GetTypeName(methodInfo, this._emitter) }), this.GetMember(methodInfo.GetMethods().Single(m => m.Name == "CreateDelegate" && m.Parameters.Count == 2 && m.Parameters[0].Type.FullName == typeof(Type).FullName && m.Parameters[1].Type.FullName == typeof(object).FullName)), this._emitter.ToJavaScript(new [] { new JRaw(ExpressionTreeBuilder.GetTypeName(rr.Type, this._emitter)), new JRaw(rr.Conversion.Method.IsStatic ? "null" : VisitResolveResult(((MethodGroupResolveResult)rr.Input).TargetResult, null)) }) }), ExpressionTreeBuilder.GetTypeName(rr.Type, this._emitter) })); } else { string methodName; if (rr.Conversion.IsTryCast) { methodName = "TypeAs"; } else if (rr.CheckForOverflow) { methodName = "ConvertChecked"; } else { methodName = "Convert"; } if (rr.Conversion.IsUserDefined) { return(CompileFactoryCall(methodName, new[] { typeof(Expression), typeof(Type), typeof(MethodInfo) }, new[] { input, ExpressionTreeBuilder.GetTypeName(rr.Type, this._emitter), this.GetMember(rr.Conversion.Method) })); } else { return(CompileFactoryCall(methodName, new[] { typeof(Expression), typeof(Type) }, new[] { input, ExpressionTreeBuilder.GetTypeName(rr.Type, this._emitter) })); } } }
// The reason this class exists is that for code like this: // int i = ...; // long n = 0; // n = n + (long)i; // The resolver will produce (and process) an CastResolveResult for the cast, // (with Conversion = implicit numeric conversion) // and then pass it into CSharpResolver.ResolveBinaryOperator(). // That method normally wraps input arguments into another conversion // (the implicit conversion applied by the operator). // However, identity conversions do not cause the creation of ConversionResolveResult instances, // so the OperatorResolveResult's argument will be the CastResolveResult // of the cast. // Without this class (and instead using ConversionResolveResult for both purposes), // it would be hard for the conversion-processing code // in the ResolveVisitor to distinguish the existing conversion from the CastExpression // from an implicit conversion introduced by the binary operator. // This would cause the conversion to be processed yet again. // The following unit tests would fail without this class: // * CastTests.ExplicitConversion_In_Assignment // * FindReferencesTest.FindReferencesForOpImplicitInAssignment_ExplicitCast // * CS0029InvalidConversionIssueTests.ExplicitConversionFromUnknownType public CastResolveResult(ConversionResolveResult rr) : base(rr.Type, rr.Input, rr.Conversion, rr.CheckForOverflow) { }
public IList<ResolveResult> GetArgumentsWithConversions() { if (bestCandidate == null) return arguments; var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { if (conversions[i] == Conversion.IdentityConversion || conversions[i] == Conversion.None) { args[i] = arguments[i]; } else { int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; IType parameterType; if (parameterIndex >= 0) parameterType = bestCandidate.ParameterTypes[parameterIndex]; else parameterType = SpecialType.UnknownType; args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]); } } return args; }
string Visit(ConversionResolveResult result) { throw new NotImplementedException(); }
Value Visit(ConversionResolveResult result) { if (result.IsError) throw new GetValueException("Cannot convert from '{0}' to '{1}'.", new CSharpAmbience().ConvertType(result.Input.Type), new CSharpAmbience().ConvertType(result.Type)); var val = Convert(result.Input); if (result.Conversion.IsBoxingConversion) return val; if (result.Conversion.IsIdentityConversion) return val; if (result.Conversion.IsNumericConversion) { var convVal = CSharpPrimitiveCast.Cast(ReflectionHelper.GetTypeCode(result.Type), val.PrimitiveValue, false); return Eval.CreateValue(evalThread, convVal); } if (result.Conversion.IsUserDefined) return InvokeMethod(null, result.Conversion.Method, val); if (result.Conversion.IsReferenceConversion && result.Conversion.IsImplicit) return val; if (result.Conversion.IsNullLiteralConversion) return val; throw new GetValueException("conversion '{0}' not implemented!", result.Conversion); }
public IList<ResolveResult> GetArgumentsWithConversions() { if (bestCandidate == null) return arguments; var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { if (conversions[i] == Conversion.IdentityConversion) { args[i] = arguments[i]; } else { int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; IType parameterType; if (parameterIndex >= 0) { parameterType = bestCandidate.ParameterTypes[parameterIndex]; } else { parameterType = SpecialType.UnknownType; } if (arguments[i].IsCompileTimeConstant && conversions[i] != Conversion.None) { args[i] = new CSharpResolver(compilation).ResolveCast(parameterType, arguments[i]); } else { args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]); } } } return args; }
internal override bool IsMatch(ResolveResult rr) { ConversionResolveResult crr = rr as ConversionResolveResult; return(crr != null && crr.Conversion.IsUserDefined && crr.Conversion.Method.MemberDefinition == op); }
public object VisitConversionResolveResult(ConversionResolveResult res) { var value = res.Input.AcceptVisitor(this); return(value); }
string Visit(ConversionResolveResult result) { throw new NotImplementedException(); }
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); } }
/// <summary> /// /// </summary> /// <param name="rr">The input resolve result that should be converted. /// If a conversion exists, it is applied to the resolve result</param> /// <param name="targetType">The target type that we should convert to</param> /// <param name="isNullable">Whether we are dealing with a lifted operator</param> /// <param name="enumRR">The resolve result that is enum-typed. /// If necessary, a nullable conversion is applied.</param> /// <param name="allowConversionFromConstantZero"> /// Whether the conversion from the constant zero is allowed. /// </param> /// <returns>True if the conversion is successful; false otherwise. /// If the conversion is not successful, the ref parameters will not be modified.</returns> bool TryConvertEnum(ref ResolveResult rr, IType targetType, ref bool isNullable, ref ResolveResult enumRR, bool allowConversionFromConstantZero = true) { Conversion c; if (!isNullable) { // Try non-nullable c = conversions.ImplicitConversion(rr, targetType); if (c.IsValid && (allowConversionFromConstantZero || !c.IsEnumerationConversion)) { rr = Convert(rr, targetType, c); return true; } } // make targetType nullable if it isn't already: if (!targetType.IsKnownType(KnownTypeCode.NullableOfT)) targetType = NullableType.Create(compilation, targetType); c = conversions.ImplicitConversion(rr, targetType); if (c.IsValid && (allowConversionFromConstantZero || !c.IsEnumerationConversion)) { rr = Convert(rr, targetType, c); isNullable = true; // Also convert the enum-typed RR to nullable, if it isn't already if (!enumRR.Type.IsKnownType(KnownTypeCode.NullableOfT)) { var nullableType = NullableType.Create(compilation, enumRR.Type); enumRR = new ConversionResolveResult(nullableType, enumRR, Conversion.ImplicitNullableConversion); } return true; } return false; }
static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, InvocationExpression invocationExpression, out MemberReferenceExpression memberRefExpr, out ResolveResult target, out Expression firstArgument) { var method = invocationExpression.GetSymbol() as IMethod; memberRefExpr = null; target = null; firstArgument = null; if (method == null || !method.IsExtensionMethod || !invocationExpression.Arguments.Any()) { return(false); } IReadOnlyList <IType> typeArguments; 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(false); } firstArgument = invocationExpression.Arguments.First(); if (firstArgument is NamedArgumentExpression) { return(false); } 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++; } return(CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames)); }
public JsFunctionDefinitionExpression CompileMethod(IList<IParameter> parameters, IDictionary<IVariable, VariableData> variables, Expression body, IType returnType, bool staticMethodWithThisAsFirstArgument, bool expandParams, StateMachineType stateMachineType, IType iteratorBlockYieldTypeOrAsyncTaskGenericArgument = null) { SetRegion(body.Region); return CompileMethod(parameters, variables, staticMethodWithThisAsFirstArgument, expandParams, stateMachineType, iteratorBlockYieldTypeOrAsyncTaskGenericArgument, () => { bool hasReturnValue = !returnType.IsKnownType(KnownTypeCode.Void); var rr = _resolver.Resolve(body); if (hasReturnValue) { var conversion = CSharpConversions.Get(_compilation).ImplicitConversion(rr, returnType); if (!conversion.IsValid) _errorReporter.InternalError("No implicit conversion found from " + rr.Type + " to " + returnType); else if (!conversion.IsIdentityConversion) rr = new ConversionResolveResult(returnType, rr, conversion); } if (!IsInvocationOfRemovedMethod(rr)) { var compiled = _expressionCompiler.Compile(rr, hasReturnValue); _result.AddRange(compiled.AdditionalStatements); if (hasReturnValue) { JsExpression result = compiled.Expression; if (IsMutableValueType(returnType)) { result = MaybeCloneValueType(result, rr, rr.Type); } _result.Add(JsStatement.Return(result)); } else if (compiled.Expression.NodeType != ExpressionNodeType.Null) // The statement "null;" is illegal in C#, so it must have appeared because there was no suitable expression to return. _result.Add(compiled.Expression); } }); }