private void BuildInterfaceInfo(INamedTypeSymbol typeSym, CSharpCompilation compilation, SymbolTable symTable) { foreach (var intf in typeSym.AllInterfaces) { if (!InterfaceSymbols.Contains(intf)) { InterfaceSymbols.Add(intf); } } if (typeSym.TypeKind != TypeKind.Interface) { foreach (var sym in typeSym.GetMembers()) { var msym = sym as IMethodSymbol; if (null != msym && msym.ExplicitInterfaceImplementations.Length > 0) { foreach (var implSym in msym.ExplicitInterfaceImplementations) { string fn = ClassInfo.GetFullName(implSym.ContainingType); ClassSymbolInfo csi; if (symTable.ClassSymbols.TryGetValue(fn, out csi)) { if (!csi.ExplicitInterfaceImplementationMethods.ContainsKey(implSym)) { csi.ExplicitInterfaceImplementationMethods.Add(implSym, msym); } } } } var psym = sym as IPropertySymbol; if (null != psym && !psym.IsIndexer && psym.ExplicitInterfaceImplementations.Length > 0) { foreach (var implSym in psym.ExplicitInterfaceImplementations) { string fn = ClassInfo.GetFullName(implSym.ContainingType); ClassSymbolInfo csi; if (symTable.ClassSymbols.TryGetValue(fn, out csi)) { if (!csi.ExplicitInterfaceImplementationProperties.ContainsKey(implSym)) { csi.ExplicitInterfaceImplementationProperties.Add(implSym, psym); } } } } var esym = sym as IEventSymbol; if (null != esym && esym.ExplicitInterfaceImplementations.Length > 0) { foreach (var implSym in esym.ExplicitInterfaceImplementations) { string fn = ClassInfo.GetFullName(implSym.ContainingType); ClassSymbolInfo csi; if (symTable.ClassSymbols.TryGetValue(fn, out csi)) { if (!csi.ExplicitInterfaceImplementationEvents.ContainsKey(implSym)) { csi.ExplicitInterfaceImplementationEvents.Add(implSym, esym); } } } } } } }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { var ci = m_ClassInfoStack.Peek(); var localSym = m_Model.GetDeclaredSymbol(node) as ILocalSymbol; if (null != localSym && localSym.HasConstantValue) { if (null != node.Initializer) { CodeBuilder.AppendFormat("{0}local({1}); {2}", GetIndentString(), node.Identifier.Text, node.Identifier.Text); } else { CodeBuilder.AppendFormat("{0}local({1})", GetIndentString(), node.Identifier.Text); } CodeBuilder.Append(" = "); OutputConstValue(localSym.ConstantValue, localSym); CodeBuilder.AppendLine(";"); return; } bool dslToObject = false; ITypeSymbol type = null; if (null != node.Initializer) { type = m_Model.GetTypeInfoEx(node.Initializer.Value).Type; if (null != localSym && null != localSym.Type && null != type) { dslToObject = InvocationInfo.IsDslToObject(localSym.Type, type); } } VisitLocalVariableDeclarator(ci, node, dslToObject); if (null != node.Initializer) { var rightSymbolInfo = m_Model.GetSymbolInfoEx(node.Initializer.Value); var rightSym = rightSymbolInfo.Symbol; if (null != type && type.IsValueType && !dslToObject && !SymbolTable.IsBasicType(type) && !CsDslTranslater.IsImplementationOfSys(type, "IEnumerator")) { if (null != rightSym && (rightSym.Kind == SymbolKind.Method || rightSym.Kind == SymbolKind.Property || rightSym.Kind == SymbolKind.Field || rightSym.Kind == SymbolKind.Local) && SymbolTable.Instance.IsCs2DslSymbol(rightSym)) { MarkNeedFuncInfo(); if (SymbolTable.Instance.IsCs2DslSymbol(type)) { CodeBuilder.AppendFormat("{0}{1} = wrapstruct({2}, {3});", GetIndentString(), node.Identifier.Text, node.Identifier.Text, ClassInfo.GetFullName(type)); CodeBuilder.AppendLine(); } else { string ns = ClassInfo.GetNamespaces(type); if (ns != "System") { CodeBuilder.AppendFormat("{0}{1} = wrapexternstruct({2}, {3});", GetIndentString(), node.Identifier.Text, node.Identifier.Text, ClassInfo.GetFullName(type)); CodeBuilder.AppendLine(); } } } } } }
public override void VisitForEachStatement(ForEachStatementSyntax node) { MethodInfo mi = m_MethodInfoStack.Peek(); mi.TryCatchUsingOrLoopSwitchStack.Push(false); ContinueInfo ci = new ContinueInfo(); ci.Init(node.Statement); m_ContinueInfoStack.Push(ci); IConversionOperation opd = null; bool isList = false; bool isArray = false; var oper = m_Model.GetOperationEx(node) as IForEachLoopOperation; if (null != oper) { opd = oper.Collection as IConversionOperation; } var expType = m_Model.GetTypeInfoEx(node.Expression).Type; if (null != expType) { isList = IsImplementationOfSys(expType, "IList"); isArray = expType.TypeKind == TypeKind.Array; } var srcPos = GetSourcePosForVar(node); if (isArray) { int rank = 0; var arrType = expType as IArrayTypeSymbol; rank = arrType.Rank; bool isCs2Dsl = SymbolTable.Instance.IsCs2DslSymbol(expType); string varIndex = string.Format("__foreach_ix_{0}", srcPos); string varExp = string.Format("__foreach_exp_{0}", srcPos); CodeBuilder.AppendFormat("{0}foreacharray({1}, {2}, {3}, ", GetIndentString(), varIndex, varExp, node.Identifier.Text); OutputExpressionSyntax(node.Expression, opd); CodeBuilder.Append(", "); CodeBuilder.Append(rank); CodeBuilder.Append(", "); CodeBuilder.Append(isCs2Dsl ? "false" : "true"); CodeBuilder.AppendLine("){"); } else if (isList) { string varIndex = string.Format("__foreach_ix_{0}", srcPos); string varExp = string.Format("__foreach_exp_{0}", srcPos); var objType = expType as INamedTypeSymbol; INamedTypeSymbol listType = null; var fobj = objType; IMethodSymbol msym = null; while (null != fobj) { if (HasItemGetMethodDefined(fobj, ref msym)) { listType = fobj; break; } fobj = fobj.BaseType; } string elemTypeName = null; string elemTypeKind = null; if (null != msym) { elemTypeName = ClassInfo.GetFullName(msym.ReturnType); elemTypeKind = "TypeKind." + msym.ReturnType.TypeKind; } if (string.IsNullOrEmpty(elemTypeName)) { elemTypeName = "null"; } if (string.IsNullOrEmpty(elemTypeKind)) { elemTypeKind = "null"; } bool isCs2Dsl = SymbolTable.Instance.IsCs2DslSymbol(listType); string objTypeName = ClassInfo.GetFullName(objType); string listTypeName = ClassInfo.GetFullName(listType); CodeBuilder.AppendFormat("{0}foreachlist({1}, {2}, {3}, ", GetIndentString(), varIndex, varExp, node.Identifier.Text); OutputExpressionSyntax(node.Expression, opd); CodeBuilder.Append(", "); CodeBuilder.Append(elemTypeName); CodeBuilder.Append(", "); CodeBuilder.Append(elemTypeKind); CodeBuilder.Append(", "); CodeBuilder.Append(objTypeName); CodeBuilder.Append(", "); CodeBuilder.Append(listTypeName); CodeBuilder.Append(", "); CodeBuilder.Append(isCs2Dsl ? "false" : "true"); CodeBuilder.AppendLine("){"); } else { MarkNeedFuncInfo(); var objType = expType as INamedTypeSymbol; INamedTypeSymbol enumType = null; var fobj = objType; while (null != fobj) { if (HasForeachDefined(fobj)) { enumType = fobj; break; } fobj = fobj.BaseType; } bool isCs2Dsl = SymbolTable.Instance.IsCs2DslSymbol(enumType); string objTypeName = ClassInfo.GetFullName(objType); string enumTypeName = ClassInfo.GetFullName(enumType); string varIter = string.Format("__foreach_{0}", srcPos); CodeBuilder.AppendFormat("{0}foreach({1}, {2}, ", GetIndentString(), varIter, node.Identifier.Text); OutputExpressionSyntax(node.Expression, opd); CodeBuilder.Append(", "); CodeBuilder.Append(objTypeName); CodeBuilder.Append(", "); CodeBuilder.Append(enumTypeName); CodeBuilder.Append(", "); CodeBuilder.Append(isCs2Dsl ? "false" : "true"); CodeBuilder.AppendLine("){"); } if (ci.HaveContinue) { if (ci.HaveBreak) { CodeBuilder.AppendFormat("{0}local({1}); {1} = false;", GetIndentString(), ci.BreakFlagVarName); CodeBuilder.AppendLine(); } CodeBuilder.AppendFormat("{0}do{{", GetIndentString()); CodeBuilder.AppendLine(); } ++m_Indent; node.Statement.Accept(this); --m_Indent; if (ci.HaveContinue) { CodeBuilder.AppendFormat("{0}}}while(false);", GetIndentString()); CodeBuilder.AppendLine(); if (ci.HaveBreak) { CodeBuilder.AppendFormat("{0}if({1}){{break;}};", GetIndentString(), ci.BreakFlagVarName); CodeBuilder.AppendLine(); } } CodeBuilder.AppendFormat("{0}}};", GetIndentString()); CodeBuilder.AppendLine(); m_ContinueInfoStack.Pop(); mi.TryCatchUsingOrLoopSwitchStack.Pop(); }
internal void Init(IMethodSymbol sym, SyntaxNode node) { ParamNames.Clear(); ReturnParamNames.Clear(); OutParamNames.Clear(); OriginalParamsName = string.Empty; ExistYield = false; ExistTopLevelReturn = false; ExistTryCatch = false; TryCatchLayer = 0; ReturnVarName = string.Empty; SemanticInfo = sym; SyntaxNode = node; if (sym.IsGenericMethod) { foreach (var param in sym.TypeParameters) { ParamNames.Add(param.Name); GenericMethodTypeParamNames.Add(param.Name); } } foreach (var param in sym.Parameters) { if (param.IsParams) { var arrTypeSym = param.Type as IArrayTypeSymbol; if (null != arrTypeSym && arrTypeSym.ElementType.TypeKind == TypeKind.Struct) { string ns = ClassInfo.GetNamespaces(arrTypeSym.ElementType); if (SymbolTable.Instance.IsCs2DslSymbol(arrTypeSym.ElementType)) { ParamsIsValueType = true; } else if (ns != "System") { ParamsIsExternValueType = true; } } ParamNames.Add("..."); OriginalParamsName = param.Name; //遇到变参直接结束(变参set_Item会出现后面带一个value参数的情形,在函数实现里处理) break; } else if (param.RefKind == RefKind.Ref) { //ref参数与out参数在形参处理时机制相同,实参时out参数传入__cs2dsl_out(适应脚本引擎与dotnet反射的调用规则) ParamNames.Add(string.Format("ref({0})", param.Name)); ReturnParamNames.Add(param.Name); } else if (param.RefKind == RefKind.Out) { //ref参数与out参数在形参处理时机制相同,实参时out参数传入__cs2dsl_out(适应脚本引擎与dotnet反射的调用规则) ParamNames.Add(string.Format("out({0})", param.Name)); ReturnParamNames.Add(param.Name); OutParamNames.Add(param.Name); } else { if (param.Type.TypeKind == TypeKind.Struct) { string ns = ClassInfo.GetNamespaces(param.Type); if (SymbolTable.Instance.IsCs2DslSymbol(param.Type)) { ValueParams.Add(ParamNames.Count); } else if (ns != "System") { ExternValueParams.Add(ParamNames.Count); } } ParamNames.Add(param.Name); } } if (!sym.ReturnsVoid) { var returnType = ClassInfo.GetFullName(sym.ReturnType); if (returnType.StartsWith(SymbolTable.PrefixExternClassName("System.Collections")) && (sym.ReturnType.Name == "IEnumerable" || sym.ReturnType.Name == "IEnumerator")) { var analysis = new YieldAnalysis(); analysis.Visit(node); ExistYield = analysis.YieldCount > 0; } } }
public override void VisitIdentifierName(IdentifierNameSyntax node) { string name = node.Identifier.Text; if (m_ClassInfoStack.Count > 0) { ClassInfo classInfo = m_ClassInfoStack.Peek(); SymbolInfo symbolInfo = m_Model.GetSymbolInfo(node); var sym = symbolInfo.Symbol; if (null != sym) { bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(sym); if (sym.Kind == SymbolKind.NamedType || sym.Kind == SymbolKind.Namespace) { string fullName = ClassInfo.GetFullName(sym); CodeBuilder.Append(fullName); if (sym.Kind == SymbolKind.NamedType) { var namedType = sym as INamedTypeSymbol; AddReferenceAndTryDeriveGenericTypeInstance(classInfo, namedType); } return; } else if (sym.Kind == SymbolKind.Field || sym.Kind == SymbolKind.Property || sym.Kind == SymbolKind.Event) { if (IsNewObjMember(name)) { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, newobj, \"{2}\")", isExtern ? "getexterninstance" : "getinstance", sym.Kind.ToString(), name); return; } if (sym.ContainingType == classInfo.SemanticInfo || sym.ContainingType == classInfo.SemanticInfo.OriginalDefinition || classInfo.IsInherit(sym.ContainingType)) { if (sym.IsStatic) { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, {2}, \"{3}\")", isExtern ? "getexternstatic" : "getstatic", sym.Kind.ToString(), classInfo.Key, sym.Name); } else { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, this, \"{2}\")", isExtern ? "getexterninstance" : "getinstance", sym.Kind.ToString(), sym.Name); } return; } } else if (sym.Kind == SymbolKind.Method && (sym.ContainingType == classInfo.SemanticInfo || sym.ContainingType == classInfo.SemanticInfo.OriginalDefinition || classInfo.IsInherit(sym.ContainingType))) { var msym = sym as IMethodSymbol; string manglingName = NameMangling(msym); var mi = new MethodInfo(); mi.Init(msym, node); if (node.Parent is InvocationExpressionSyntax) { if (sym.IsStatic) { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, {2}, \"{3}\")", isExtern ? "getexternstatic" : "getstatic", sym.Kind.ToString(), classInfo.Key, manglingName); } else { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, this, \"{2}\")", isExtern ? "getexterninstance" : "getinstance", sym.Kind.ToString(), manglingName); } } else { string className = ClassInfo.GetFullName(msym.ContainingType); string delegationKey = string.Format("{0}:{1}", className, manglingName); string varName = string.Format("__delegation_{0}", GetSourcePosForVar(node)); CodeBuilder.Append("(function(){ "); string paramsString = string.Join(", ", mi.ParamNames.ToArray()); if (msym.IsStatic) { CodeBuilder.AppendFormat("builddelegation(\"{0}\", {1}, \"{2}\", {3}, {4}, {5}, {6});", paramsString, varName, delegationKey, className, manglingName, msym.ReturnsVoid ? "false" : "true", msym.IsStatic ? "true" : "false"); } else { CodeBuilder.AppendFormat("builddelegation(\"{0}\", {1}, \"{2}\", {3}, {4}, {5}, {6});", paramsString, varName, delegationKey, "this", manglingName, msym.ReturnsVoid ? "false" : "true", msym.IsStatic ? "true" : "false"); } CodeBuilder.Append(" })()"); } return; } } else { SymbolKind kind; if (IsNewObjMember(name, out kind)) { CodeBuilder.AppendFormat("getinstance(SymbolKind.{0}, newobj, \"{1}\")", kind.ToString(), name); return; } ReportIllegalSymbol(node, symbolInfo); } } CodeBuilder.Append(name); }
internal bool IsIgnoredSymbol(ITypeSymbol sym) { return(m_IgnoredTypes.ContainsKey(ClassInfo.GetFullName(sym))); }
internal string CalcFullNameAndTypeArguments(INamedTypeSymbol sym) { var name = ClassInfo.GetFullName(sym); return(CalcFullNameAndTypeArguments(name, sym)); }
internal static void CheckInvocation(IMethodSymbol sym, IMethodSymbol callerSym) { if (!SymbolTable.EnableTranslationCheck) { return; } if (ClassInfo.HasAttribute(sym, "Cs2Dsl.DontCheckAttribute")) { return; } if (null != callerSym && ClassInfo.HasAttribute(callerSym, "Cs2Dsl.DontCheckAttribute")) { return; } if (null != callerSym && ClassInfo.HasAttribute(callerSym.ContainingType, "Cs2Dsl.DontCheckAttribute")) { return; } if (!SymbolTable.Instance.IsCs2DslSymbol(sym)) { var ckey = ClassInfo.GetFullName(sym.ContainingType); var id = string.Format("{0}.{1}", ckey, sym.Name); if (!SymbolTable.Instance.CheckedInvocations.Contains(id)) { SymbolTable.Instance.CheckedInvocations.Add(id); bool isOverload = false; ClassSymbolInfo info; if (SymbolTable.Instance.ClassSymbols.TryGetValue(ckey, out info)) { info.SymbolOverloadFlags.TryGetValue(sym.Name, out isOverload); } string callerInfo = string.Empty; if (null != callerSym) { var callerClass = ClassInfo.GetFullName(callerSym.ContainingType); var callerMethod = SymbolTable.Instance.NameMangling(callerSym); callerInfo = string.Format(" caller:{0}.{1}", callerClass, callerMethod); } if (sym.IsExtensionMethod && !SymbolTable.Instance.IsLegalExtension(sym.ContainingType)) { //不支持的语法 Logger.Instance.Log("Translation Error", "unsupported extern extension method {0}.{1} !{2}", ckey, sym.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } else { if (SymbolTable.Instance.IsIllegalMethod(sym)) { Logger.Instance.Log("Translation Error", "unsupported extern method {0}.{1} !{2}", ckey, sym.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } if (sym.ContainingType.TypeKind == TypeKind.Delegate || sym.ContainingType.IsGenericType && SymbolTable.Instance.IsLegalGenericType(sym.ContainingType, true) || sym.IsGenericMethod && SymbolTable.Instance.IsLegalGenericMethod(sym)) { //如果是标记为合法的泛型类或委托类型的成员,则不用再进行类型检查 } else { foreach (var param in sym.Parameters) { var type = param.Type as INamedTypeSymbol; if (param.IsParams && isOverload) { Logger.Instance.Log("Translation Warning", "extern overloaded method {0}.{1} parameter {2} is params, please check export api code !{3}", ckey, sym.Name, param.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); continue; } if (null != type && type.TypeKind != TypeKind.Delegate) { if (type.IsGenericType) { if (!SymbolTable.Instance.IsLegalParameterGenericType(type)) { Logger.Instance.Log("Translation Error", "extern method {0}.{1} parameter {2} is generic type, please replace with non generic type !{3}", ckey, sym.Name, param.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } else { if (SymbolTable.Instance.IsIllegalType(type)) { Logger.Instance.Log("Translation Error", "extern method {0}.{1} parameter {2} is unsupported type, please replace with non generic type !{3}", ckey, sym.Name, param.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } } } if (!sym.ReturnsVoid) { var type = sym.ReturnType as INamedTypeSymbol; if (null != type && type.TypeKind != TypeKind.Delegate) { if (type.IsGenericType) { if (!SymbolTable.Instance.IsLegalParameterGenericType(type)) { Logger.Instance.Log("Translation Error", "extern method {0}.{1} return {2} is generic type, please replace with non generic type !{3}", ckey, sym.Name, type.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } else { if (SymbolTable.Instance.IsIllegalType(type)) { Logger.Instance.Log("Translation Error", "extern method {0}.{1} return {2} is unsupported type, please replace with non generic type !{3}", ckey, sym.Name, type.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } } } } } } }
internal static void CheckInvocation(SemanticModel model, IMethodSymbol sym, IList <ExpressionSyntax> args, IList <ArgDefaultValueInfo> defValArgs, IList <IConversionExpression> argConversions, SyntaxNode node, IMethodSymbol callerSym) { if (!SymbolTable.EnableTranslationCheck) { return; } if (ClassInfo.HasAttribute(sym, "Cs2Dsl.DontCheckAttribute")) { return; } if (null != callerSym && ClassInfo.HasAttribute(callerSym, "Cs2Dsl.DontCheckAttribute")) { return; } if (null != callerSym && ClassInfo.HasAttribute(callerSym.ContainingType, "Cs2Dsl.DontCheckAttribute")) { return; } if (!SymbolTable.Instance.IsCs2DslSymbol(sym)) { var ckey = ClassInfo.GetFullName(sym.ContainingType); var oper = null != node?model.GetOperationEx(node) as IInvocationExpression : null; var realType = null != oper && null != oper.Instance ? oper.Instance.Type : null; bool isOverload = false; ClassSymbolInfo info; if (SymbolTable.Instance.ClassSymbols.TryGetValue(ckey, out info)) { info.SymbolOverloadFlags.TryGetValue(sym.Name, out isOverload); } string callerInfo = string.Empty; if (null != callerSym) { var callerClass = ClassInfo.GetFullName(callerSym.ContainingType); var callerMethod = SymbolTable.Instance.NameCs2DslMangling(callerSym); callerInfo = string.Format(" caller:{0}.{1}", callerClass, callerMethod); } if (sym.IsExtensionMethod && !SymbolTable.Instance.IsLegalExtension(sym.ContainingType)) { //不支持的语法 Logger.Instance.Log(node, "unsupported extern extension method {0}.{1} !{2}", ckey, sym.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } else { if (SymbolTable.Instance.IsIllegalMethod(sym)) { Logger.Instance.Log(node, "unsupported extern method {0}.{1} !{2}", ckey, sym.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } if (sym.ContainingType.TypeKind == TypeKind.Delegate || (null == realType || realType == sym.ContainingType) && sym.ContainingType.IsGenericType && SymbolTable.Instance.IsLegalGenericType(sym.ContainingType, true) || sym.IsGenericMethod && SymbolTable.Instance.IsLegalGenericMethod(sym)) { //如果是标记为合法的泛型类或委托类型的成员,则不用再进行类型检查 } else { int ix = 0; foreach (var param in sym.Parameters) { IOperation argOper = null; if (ix < args.Count) { argOper = null != args[ix] ? model.GetOperationEx(args[ix]) : null; } else if (ix < args.Count + defValArgs.Count) { argOper = defValArgs[ix - args.Count].OperOrSym as IOperation; } IConversionExpression argConv = null; if (ix < argConversions.Count) { argConv = argConversions[ix]; } ++ix; INamedTypeSymbol argType = null; if (null != argOper && (null == argConv || !argConv.UsesOperatorMethod)) { argType = argOper.Type as INamedTypeSymbol; } var paramType = param.Type as INamedTypeSymbol; if (param.IsParams && isOverload) { Logger.Instance.Log(node, "extern overloaded method {0}.{1} parameter {2} is params, please check export api code !{3}", ckey, sym.Name, param.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); continue; } if (null != paramType && paramType.TypeKind != TypeKind.Delegate) { bool isContainerIntf = paramType.Name == "IEnumerable" || paramType.Name == "ICollection" || paramType.Name == "IDictionary" || paramType.Name == "IList"; if (null != realType && SymbolTable.Instance.IsCs2DslSymbol(realType) && isContainerIntf && null != argType && (argType.IsGenericType || SymbolTable.Instance.IsCs2DslSymbol(argType))) { Logger.Instance.Log(node, "extern method {0}.{1} parameter {2} can't assign a script object to it !{3}", ckey, sym.Name, param.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } else if (paramType.IsGenericType) { if (!SymbolTable.Instance.IsLegalParameterGenericType(paramType)) { Logger.Instance.Log(node, "extern method {0}.{1} parameter {2} is generic type, please replace with non generic type !{3}", ckey, sym.Name, param.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } else { if (SymbolTable.Instance.IsIllegalType(paramType)) { Logger.Instance.Log(node, "extern method {0}.{1} parameter {2} is unsupported type, please replace with non generic type !{3}", ckey, sym.Name, param.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } } } if (!sym.ReturnsVoid) { var type = sym.ReturnType as INamedTypeSymbol; if (null != type && type.TypeKind != TypeKind.Delegate) { if (type.IsGenericType) { if (!SymbolTable.Instance.IsLegalParameterGenericType(type)) { Logger.Instance.Log(node, "extern method {0}.{1} return {2} is generic type, please replace with non generic type !{3}", ckey, sym.Name, type.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } else { if (SymbolTable.Instance.IsIllegalType(type)) { Logger.Instance.Log(node, "extern method {0}.{1} return {2} is unsupported type, please replace with non generic type !{3}", ckey, sym.Name, type.Name, string.IsNullOrEmpty(callerInfo) ? string.Empty : callerInfo); } } } } } } }
internal string CalcTryUsingFuncOptions(DataFlowAnalysis dataFlow, ControlFlowAnalysis ctrlFlow, List <string> inputs, List <string> outputs) { string returnType = "System.Int32"; string returnTypeKind = "TypeKind.Struct"; bool returnTypeIsExtern = false; var sb = new StringBuilder(); sb.AppendFormat("needfuncinfo({0}), rettype(return, {1}, {2}, 0, true)", NeedFuncInfo ? "true" : "false", returnType, returnTypeKind); if (ctrlFlow.ReturnStatements.Length > 0 && !string.IsNullOrEmpty(ReturnVarName)) { returnType = ClassInfo.GetFullName(SemanticInfo.ReturnType); if (string.IsNullOrEmpty(returnType)) { returnType = "null"; } returnTypeKind = "TypeKind." + SemanticInfo.ReturnType.TypeKind.ToString(); returnTypeIsExtern = !SymbolTable.Instance.IsCs2DslSymbol(SemanticInfo.ReturnType); sb.Append(", "); sb.AppendFormat("rettype({0}, {1}, {2}, 1, {3})", ReturnVarName, returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false"); } foreach (var v in dataFlow.DataFlowsOut) { sb.Append(", "); int refOrOut = 2; if (inputs.Contains(v.Name)) { refOrOut = 1; } var psym = v as IParameterSymbol; var lsym = v as ILocalSymbol; if (null != psym) { var type = ClassInfo.GetFullName(psym.Type); var typeKind = psym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } else if (null != lsym) { var type = ClassInfo.GetFullName(lsym.Type); var typeKind = lsym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } } if (ctrlFlow.ReturnStatements.Length > 0 && !string.IsNullOrEmpty(ReturnVarName)) { sb.Append(", "); sb.AppendFormat("paramtype({0}, {1}, {2}, 1, {3})", ReturnVarName, returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false"); } foreach (var v in dataFlow.DataFlowsIn) { if (v.Name == "this") { continue; } sb.Append(", "); int refOrOut = 0; if (outputs.Contains(v.Name)) { refOrOut = 1; } var psym = v as IParameterSymbol; var lsym = v as ILocalSymbol; if (null != psym) { var type = ClassInfo.GetFullName(psym.Type); var typeKind = psym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } else if (null != lsym) { var type = ClassInfo.GetFullName(lsym.Type); var typeKind = lsym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } } foreach (var v in dataFlow.DataFlowsOut) { sb.Append(", "); int refOrOut = 2; if (inputs.Contains(v.Name)) { refOrOut = 1; } var psym = v as IParameterSymbol; var lsym = v as ILocalSymbol; if (null != psym) { var type = ClassInfo.GetFullName(psym.Type); var typeKind = psym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } else if (null != lsym) { var type = ClassInfo.GetFullName(lsym.Type); var typeKind = lsym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } } return(sb.ToString()); }
private void VisitTypeDeclarationSyntax(TypeDeclarationSyntax node) { INamedTypeSymbol declSym = m_Model.GetDeclaredSymbol(node); SymbolTable.Instance.AddGenericTypeDefine(ClassInfo.GetFullNameWithTypeParameters(declSym), node); }
internal string CalcFunctionOptions() { if (string.IsNullOrEmpty(FunctionOptions)) { string returnName = "return"; string returnType; string returnTypeKind; bool returnTypeIsExtern = false; if (SemanticInfo.ReturnsVoid) { returnType = "System.Void"; returnTypeKind = "TypeKind.Unknown"; } else { returnType = ClassInfo.GetFullName(SemanticInfo.ReturnType); if (SemanticInfo.ReturnType.TypeKind == TypeKind.TypeParameter) { var retTypeParam = SemanticInfo.ReturnType as ITypeParameterSymbol; if (null != retTypeParam && retTypeParam.ConstraintTypes.Length > 0) { returnName = returnType; returnType = ClassInfo.GetFullName(retTypeParam.ConstraintTypes[0]); } } if (string.IsNullOrEmpty(returnType)) { returnType = "null"; } returnTypeKind = "TypeKind." + SemanticInfo.ReturnType.TypeKind.ToString(); returnTypeIsExtern = !SymbolTable.Instance.IsCs2DslSymbol(SemanticInfo.ReturnType); } var sb = new StringBuilder(); sb.AppendFormat("needfuncinfo({0}), rettype({1}, {2}, {3}, 0, {4})", NeedFuncInfo ? "true" : "false", returnName, returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false"); for (int ix = 0; ix < ReturnParamNames.Count; ++ix) { var name = ReturnParamNames[ix]; var type = ReturnParamTypes[ix]; if (string.IsNullOrEmpty(type)) { type = "null"; } var typekind = ReturnParamTypeKinds[ix]; var refOrOut = ReturnParamRefOrOuts[ix]; var isExtern = ReturnParamIsExterns[ix]; sb.Append(", "); sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", name, type, typekind, refOrOut, isExtern ? "true" : "false"); } for (int ix = 0; ix < ParamNames.Count; ++ix) { var name = ParamNames[ix]; var type = ParamTypes[ix]; if (string.IsNullOrEmpty(type)) { type = "null"; } var typekind = ParamTypeKinds[ix]; var refOrOut = ParamRefOrOuts[ix]; var isExtern = ParamIsExterns[ix]; sb.Append(", "); sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", name, type, typekind, refOrOut, isExtern ? "true" : "false"); } FunctionOptions = sb.ToString(); } return(FunctionOptions); }
public override void VisitIdentifierName(IdentifierNameSyntax node) { string name = node.Identifier.Text; if (m_ClassInfoStack.Count > 0) { ClassInfo classInfo = m_ClassInfoStack.Peek(); SymbolInfo symbolInfo = m_Model.GetSymbolInfoEx(node); var sym = symbolInfo.Symbol; if (null != sym) { bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(sym); if (sym.Kind == SymbolKind.NamedType || sym.Kind == SymbolKind.Namespace) { string fullName = ClassInfo.GetFullName(sym); CodeBuilder.Append(fullName); if (sym.Kind == SymbolKind.NamedType) { var namedType = sym as INamedTypeSymbol; AddReferenceAndTryDeriveGenericTypeInstance(classInfo, namedType); } return; } else if (sym.Kind == SymbolKind.Field || sym.Kind == SymbolKind.Property || sym.Kind == SymbolKind.Event) { var fsym = sym as IFieldSymbol; var psym = sym as IPropertySymbol; string fullName = ClassInfo.GetFullName(sym.ContainingType); if (sym.IsStatic) { if (isExtern && null != fsym && fsym.Type.IsValueType && !SymbolTable.IsBasicType(fsym.Type)) { MarkNeedFuncInfo(); CodeBuilder.AppendFormat("getexternstaticstructmember(SymbolKind.{0}, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else if (isExtern && null != psym && psym.Type.IsValueType && !SymbolTable.IsBasicType(psym.Type)) { MarkNeedFuncInfo(); CodeBuilder.AppendFormat("getexternstaticstructmember(SymbolKind.{0}, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else { string luaLibFunc; if (null != fsym && SymbolTable.Instance.IsInvokeToLuaLibField(fsym, out luaLibFunc)) { OutputInvokeToLuaLib(true, luaLibFunc, fsym.Type, "SymbolKind."); CodeBuilder.AppendFormat("{0}, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else if (null != psym && SymbolTable.Instance.IsInvokeToLuaLibProperty(psym, out luaLibFunc)) { OutputInvokeToLuaLib(true, luaLibFunc, psym.Type, "SymbolKind."); CodeBuilder.AppendFormat("{0}, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, {2}, \"{3}\")", isExtern ? "getexternstatic" : "getstatic", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } } return; } else if (IsNewObjMember(name)) { if (isExtern && null != fsym && fsym.Type.IsValueType && !SymbolTable.IsBasicType(fsym.Type)) { MarkNeedFuncInfo(); CodeBuilder.AppendFormat("getexterninstancestructmember(SymbolKind.{0}, newobj, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, name); } else if (isExtern && null != psym && psym.Type.IsValueType && !SymbolTable.IsBasicType(psym.Type)) { MarkNeedFuncInfo(); CodeBuilder.AppendFormat("getexterninstancestructmember(SymbolKind.{0}, newobj, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, name); } else { string luaLibFunc; if (null != fsym && SymbolTable.Instance.IsInvokeToLuaLibField(fsym, out luaLibFunc)) { OutputInvokeToLuaLib(true, luaLibFunc, fsym.Type, "SymbolKind."); CodeBuilder.AppendFormat("{0}, {1}, newobj, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else if (null != psym && SymbolTable.Instance.IsInvokeToLuaLibProperty(psym, out luaLibFunc)) { OutputInvokeToLuaLib(true, luaLibFunc, psym.Type, "SymbolKind."); CodeBuilder.AppendFormat("{0}, {1}, newobj, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, newobj, {2}, \"{3}\")", isExtern ? "getexterninstance" : "getinstance", SymbolTable.Instance.GetSymbolKind(sym), fullName, name); } } return; } else if (sym.ContainingType == classInfo.SemanticInfo || sym.ContainingType == classInfo.SemanticInfo.OriginalDefinition || classInfo.IsInherit(sym.ContainingType)) { if (isExtern && null != fsym && fsym.Type.IsValueType && !SymbolTable.IsBasicType(fsym.Type)) { MarkNeedFuncInfo(); CodeBuilder.AppendFormat("getexterninstancestructmember(SymbolKind.{0}, this, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else if (isExtern && null != psym && psym.Type.IsValueType && !SymbolTable.IsBasicType(psym.Type)) { MarkNeedFuncInfo(); CodeBuilder.AppendFormat("getexterninstancestructmember(SymbolKind.{0}, this, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else { string luaLibFunc; if (null != fsym && SymbolTable.Instance.IsInvokeToLuaLibField(fsym, out luaLibFunc)) { OutputInvokeToLuaLib(true, luaLibFunc, fsym.Type, "SymbolKind."); CodeBuilder.AppendFormat("{0}, this, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else if (null != psym && SymbolTable.Instance.IsInvokeToLuaLibProperty(psym, out luaLibFunc)) { OutputInvokeToLuaLib(true, luaLibFunc, psym.Type, "SymbolKind."); CodeBuilder.AppendFormat("{0}, this, {1}, \"{2}\")", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } else { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, this, {2}, \"{3}\")", isExtern ? "getexterninstance" : "getinstance", SymbolTable.Instance.GetSymbolKind(sym), fullName, sym.Name); } } return; } } else if (sym.Kind == SymbolKind.Method) { var msym = sym as IMethodSymbol; string manglingName = NameMangling(msym); var mi = new MethodInfo(); mi.Init(msym, node); string fullName = ClassInfo.GetFullName(sym.ContainingType); if (sym.IsStatic && node.Parent is InvocationExpressionSyntax) { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, {2}, \"{3}\")", isExtern ? "getexternstatic" : "getstatic", SymbolTable.Instance.GetSymbolKind(sym), fullName, manglingName); return; } else if (sym.ContainingType == classInfo.SemanticInfo || sym.ContainingType == classInfo.SemanticInfo.OriginalDefinition || classInfo.IsInherit(sym.ContainingType)) { if (node.Parent is InvocationExpressionSyntax) { CodeBuilder.AppendFormat("{0}(SymbolKind.{1}, this, {2}, \"{3}\")", isExtern ? "getexterninstance" : "getinstance", SymbolTable.Instance.GetSymbolKind(sym), fullName, manglingName); } else { string srcPos = GetSourcePosForVar(node); string delegationKey = string.Format("{0}:{1}", fullName, manglingName); if (msym.IsStatic) { CodeBuilder.AppendFormat("builddelegation(\"{0}\", \"{1}\", {2}, {3}, {4})", srcPos, delegationKey, fullName, manglingName, "true"); } else { CodeBuilder.AppendFormat("builddelegation(\"{0}\", \"{1}\", this, {2}, {3})", srcPos, delegationKey, manglingName, "false"); } } return; } } } else { string fn; SymbolKind kind; if (IsNewObjMember(name, out fn, out kind)) { CodeBuilder.AppendFormat("getinstance(SymbolKind.{0}, newobj, {1}, \"{2}\")", kind.ToString(), fn, name); return; } ReportIllegalSymbol(node, symbolInfo); } } CodeBuilder.Append(name); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { var ci = m_ClassInfoStack.Peek(); var localSym = m_Model.GetDeclaredSymbol(node) as ILocalSymbol; if (null != localSym && localSym.HasConstantValue) { if (null != node.Initializer) { CodeBuilder.AppendFormat("{0}local({1}); {2}", GetIndentString(), node.Identifier.Text, node.Identifier.Text); } else { CodeBuilder.AppendFormat("{0}local({1})", GetIndentString(), node.Identifier.Text); } CodeBuilder.Append(" = "); OutputConstValue(localSym.ConstantValue, localSym); CodeBuilder.AppendLine(";"); return; } bool dslToObject = false; ITypeSymbol type = null; if (null != node.Initializer) { type = m_Model.GetTypeInfoEx(node.Initializer.Value).Type; if (null != localSym && null != localSym.Type && null != type) { dslToObject = InvocationInfo.IsDslToObject(localSym.Type, type); } } VisitLocalVariableDeclarator(ci, node, dslToObject); if (null != node.Initializer) { var valSyntax = node.Initializer.Value; var rightType = m_Model.GetTypeInfoEx(valSyntax).Type; var rightOper = m_Model.GetOperationEx(valSyntax); if (null == rightType && null != rightOper) { rightType = rightOper.Type; } ; bool needWrapStruct = NeedWrapStruct(valSyntax, rightType, rightOper, dslToObject); if (needWrapStruct) { MarkNeedFuncInfo(); if (SymbolTable.Instance.IsCs2DslSymbol(type)) { CodeBuilder.AppendFormat("{0}{1} = wrapstruct({2}, {3});", GetIndentString(), node.Identifier.Text, node.Identifier.Text, ClassInfo.GetFullName(type)); CodeBuilder.AppendLine(); } else { string ns = ClassInfo.GetNamespaces(type); if (ns != "System") { CodeBuilder.AppendFormat("{0}{1} = wrapexternstruct({2}, {3});", GetIndentString(), node.Identifier.Text, node.Identifier.Text, ClassInfo.GetFullName(type)); CodeBuilder.AppendLine(); } } } } }
internal void Init(INamedTypeSymbol typeSym, CSharpCompilation compilation, SymbolTable symTable) { if (typeSym.TypeKind == TypeKind.Error) { Logger.Instance.ReportIllegalType(typeSym); return; } IsInterface = typeSym.TypeKind == TypeKind.Interface; foreach (var intf in typeSym.AllInterfaces) { string key = ClassInfo.GetFullName(intf); ClassSymbolInfo isi; if (!symTable.ClassSymbols.TryGetValue(key, out isi)) { isi = new ClassSymbolInfo(); symTable.ClassSymbols.Add(key, isi); isi.Init(intf, compilation, symTable); } } ClassKey = ClassInfo.GetFullName(typeSym); BaseClassKey = ClassInfo.GetFullName(typeSym.BaseType); if (BaseClassKey == "System.Object" || BaseClassKey == "System.ValueType") { BaseClassKey = string.Empty; } ExistConstructor = false; ExistStaticConstructor = false; if (typeSym.GetAttributes().Length > 0) { ExistAttributes = true; } Dictionary <string, int> fieldCounts = new Dictionary <string, int>(); Dictionary <string, int> methodCounts = new Dictionary <string, int>(); SymbolTable.Instance.CalcMemberCount(ClassKey, methodCounts, fieldCounts); bool fieldUseExplicitTypeParams = false; bool staticUseExplicitTypeParams = false; TypeSymbol = typeSym; var members = typeSym.GetMembers(); foreach (var sym in members) { var fsym = sym as IFieldSymbol; if (null != fsym) { FieldSymbols.Add(fsym); if (fsym.GetAttributes().Length > 0) { ExistAttributes = true; } CheckFieldUseExplicitTypeParam(fsym, compilation, ref fieldUseExplicitTypeParams, ref staticUseExplicitTypeParams); } } foreach (var sym in members) { var msym = sym as IMethodSymbol; if (null != msym) { if (msym.MethodKind == MethodKind.Constructor && !msym.IsImplicitlyDeclared) { ExistConstructor = true; } else if (msym.MethodKind == MethodKind.StaticConstructor && !msym.IsImplicitlyDeclared) { ExistStaticConstructor = true; } MethodSymbols.Add(msym); if (msym.GetAttributes().Length > 0) { ExistAttributes = true; } string name = msym.Name; if (name[0] == '.') { name = name.Substring(1); } bool isOverloaded; int count; if (msym.MethodKind == MethodKind.Constructor && msym.ContainingType.IsValueType) { //值类型构造都按重载处理,总是会生成一个默认构造 isOverloaded = true; } else if (methodCounts.TryGetValue(name, out count)) { isOverloaded = count > 1; } else { isOverloaded = false; } if (!SymbolOverloadFlags.ContainsKey(name)) { SymbolOverloadFlags.Add(name, isOverloaded); } else { SymbolOverloadFlags[name] = isOverloaded; } continue; } var psym = sym as IPropertySymbol; if (null != psym && !psym.IsIndexer) { PropertySymbols.Add(psym); if (psym.GetAttributes().Length > 0) { ExistAttributes = true; } continue; } var esym = sym as IEventSymbol; if (null != esym) { EventSymbols.Add(esym); if (esym.GetAttributes().Length > 0) { ExistAttributes = true; } continue; } } BuildInterfaceInfo(typeSym, compilation, symTable); }
internal static void CheckMemberAccess(SemanticModel model, MemberAccessExpressionSyntax node, IMethodSymbol callerSym) { var esym = model.GetSymbolInfoEx(node).Symbol as IEventSymbol; var psym = model.GetSymbolInfoEx(node).Symbol as IPropertySymbol; var fsym = model.GetSymbolInfoEx(node).Symbol as IFieldSymbol; var msym = model.GetSymbolInfoEx(node).Symbol as IMethodSymbol; var oper = model.GetOperationEx(node); bool isExtern = false; INamedTypeSymbol classType = null; if (null != esym && !SymbolTable.Instance.IsCs2DslSymbol(esym)) { isExtern = true; classType = esym.ContainingType; Logger.Instance.Log(node, "unsupported extern event '{0}.{1}' !", ClassInfo.GetFullName(esym.ContainingType), esym.Name); } if (null != psym && !SymbolTable.Instance.IsCs2DslSymbol(psym)) { isExtern = true; classType = psym.ContainingType; if (SymbolTable.Instance.IsIllegalProperty(psym)) { Logger.Instance.Log(node, "unsupported extern property '{0}.{1}' !", ClassInfo.GetFullName(psym.ContainingType), psym.Name); } } if (null != fsym && !SymbolTable.Instance.IsCs2DslSymbol(fsym)) { isExtern = true; classType = fsym.ContainingType; if (SymbolTable.Instance.IsIllegalField(fsym)) { Logger.Instance.Log(node, "unsupported extern field '{0}.{1}' !", ClassInfo.GetFullName(fsym.ContainingType), fsym.Name); } } if (null != msym && !(node.Parent is InvocationExpressionSyntax) && !SymbolTable.Instance.IsCs2DslSymbol(msym.ContainingType)) { if (SymbolTable.Instance.IsIllegalMethod(msym)) { Logger.Instance.Log(node, "unsupported extern event '{0}.{1}' !", ClassInfo.GetFullName(msym.ContainingType), msym.Name); } } if (isExtern && null != oper) { SymbolTable.TryRemoveNullable(ref classType); if (null != classType && (classType.TypeKind == TypeKind.Delegate || classType.IsGenericType && SymbolTable.Instance.IsLegalGenericType(classType, true))) { //如果是标记为合法的泛型类或委托类型的成员,则不用再进行类型检查 } else { var type = oper.Type as INamedTypeSymbol; SymbolTable.TryRemoveNullable(ref type); if (null != type && !SymbolTable.Instance.IsCs2DslSymbol(type) && type.TypeKind != TypeKind.Delegate) { if (type.IsGenericType) { if (!SymbolTable.Instance.IsLegalParameterGenericType(type)) { Logger.Instance.Log(node, "unsupported extern type '{0}' from member access !", SymbolTable.Instance.CalcFullNameAndTypeArguments(type)); } } else { if (SymbolTable.Instance.IsIllegalType(type)) { Logger.Instance.Log(node, "unsupported extern type '{0}' from member access !", SymbolTable.Instance.CalcFullNameAndTypeArguments(type)); } } } } } }
internal static string CalcMethodMangling(IMethodSymbol methodSym) { IAssemblySymbol assemblySym = SymbolTable.Instance.AssemblySymbol; if (null == methodSym) { return(string.Empty); } StringBuilder sb = new StringBuilder(); string name = GetMethodName(methodSym); if (!string.IsNullOrEmpty(name) && name[0] == '.') { name = name.Substring(1); } sb.Append(name); if (SymbolTable.Instance.IsCs2DslSymbol(methodSym)) { foreach (var tparam in methodSym.TypeParameters) { sb.Append("_"); sb.Append(tparam.Name); } foreach (var param in methodSym.Parameters) { sb.Append("__"); if (param.RefKind == RefKind.Ref) { sb.Append("Ref_"); } else if (param.RefKind == RefKind.Out) { sb.Append("Out_"); } var oriparam = param.OriginalDefinition; if (oriparam.Type.Kind == SymbolKind.ArrayType) { sb.Append("Arr_"); var arrSym = oriparam.Type as IArrayTypeSymbol; string fn; if (arrSym.ElementType.TypeKind == TypeKind.TypeParameter) { fn = ClassInfo.GetFullNameWithTypeParameters(arrSym.ElementType); } else { fn = ClassInfo.GetFullName(arrSym.ElementType); } sb.Append(fn.Replace('.', '_')); } else if (oriparam.Type.TypeKind == TypeKind.TypeParameter) { string fn = ClassInfo.GetFullNameWithTypeParameters(oriparam.Type); sb.Append(fn.Replace('.', '_')); } else { //这里使用泛型形参名作为函数签名的一部分,主要是为适应泛型类实例化后仍能保持函数签名一致 //因此导致的缺陷是不能支持依靠泛型类型的实参类型来区分的重载函数(这时候就在c#里给函数换个名字吧) string fn = ClassInfo.GetFullName(oriparam.Type); sb.Append(fn.Replace('.', '_')); } } } return(sb.ToString()); }
internal void Init(IMethodSymbol sym, SyntaxNode node) { TryCatchUsingOrLoopSwitchStack.Clear(); TempReturnAnalysisStack.Clear(); ParamNames.Clear(); ReturnParamNames.Clear(); OriginalParamsName = string.Empty; ExistYield = false; ExistTopLevelReturn = false; ExistTry = false; TryUsingLayer = 0; ReturnVarName = string.Empty; SemanticInfo = sym; SyntaxNode = node; if (!sym.IsExtensionMethod && sym.IsGenericMethod) { //不是扩展方法,泛型参数放在参数表最前面 foreach (var param in sym.TypeParameters) { ParamNames.Add(param.Name); if (param.ConstraintTypes.Length > 0) { ParamTypes.Add(ClassInfo.GetFullName(param.ConstraintTypes[0])); } else if (param.HasReferenceTypeConstraint) { ParamTypes.Add("System.Object"); } else if (param.HasValueTypeConstraint) { ParamTypes.Add("System.ValueType"); } else { ParamTypes.Add("null"); } ParamTypeKinds.Add("TypeKind." + param.TypeKind.ToString()); } } bool first = true; foreach (var param in sym.Parameters) { if (param.IsParams) { var arrTypeSym = param.Type as IArrayTypeSymbol; if (null != arrTypeSym) { string elementType = ClassInfo.GetFullName(arrTypeSym.ElementType); string elementTypeKind = "TypeKind." + arrTypeSym.ElementType.TypeKind.ToString(); ParamsElementInfo = string.Format("{0}, {1}", elementType, elementTypeKind); if (arrTypeSym.ElementType.IsValueType && !SymbolTable.IsBasicType(arrTypeSym.ElementType) && !CsDslTranslater.IsImplementationOfSys(arrTypeSym.ElementType, "IEnumerator")) { string ns = ClassInfo.GetNamespaces(arrTypeSym.ElementType); if (SymbolTable.Instance.IsCs2DslSymbol(arrTypeSym.ElementType)) { NeedFuncInfo = true; } else if (ns != "System") { NeedFuncInfo = true; } } } ParamNames.Add("..."); ParamTypes.Add(ClassInfo.GetFullName(param.Type)); ParamTypeKinds.Add("TypeKind." + param.Type.TypeKind.ToString()); OriginalParamsName = param.Name; //遇到变参直接结束(变参set_Item会出现后面带一个value参数的情形,在函数实现里处理) break; } else if (param.RefKind == RefKind.Ref) { if (param.Type.IsValueType && !SymbolTable.IsBasicType(param.Type) && !CsDslTranslater.IsImplementationOfSys(param.Type, "IEnumerator")) { string ns = ClassInfo.GetNamespaces(param.Type); if (SymbolTable.Instance.IsCs2DslSymbol(param.Type)) { ValueParams.Add(ParamNames.Count); NeedFuncInfo = true; } else if (ns != "System") { ExternValueParams.Add(ParamNames.Count); NeedFuncInfo = true; } } //ref参数与out参数在形参处理时机制相同,实参时out参数传入__cs2dsl_out(适应脚本引擎与dotnet反射的调用规则) ParamNames.Add(param.Name); ParamTypes.Add(ClassInfo.GetFullName(param.Type)); ParamTypeKinds.Add("TypeKind." + param.Type.TypeKind.ToString()); ReturnParamNames.Add(param.Name); } else if (param.RefKind == RefKind.Out) { if (param.Type.IsValueType && !SymbolTable.IsBasicType(param.Type) && !CsDslTranslater.IsImplementationOfSys(param.Type, "IEnumerator")) { string ns = ClassInfo.GetNamespaces(param.Type); if (SymbolTable.Instance.IsCs2DslSymbol(param.Type)) { OutValueParams.Add(ParamNames.Count); NeedFuncInfo = true; } else if (ns != "System") { OutExternValueParams.Add(ParamNames.Count); NeedFuncInfo = true; } } //ref参数与out参数在形参处理时机制相同,实参时out参数传入__cs2dsl_out(适应脚本引擎与dotnet反射的调用规则) ParamNames.Add(param.Name); ParamTypes.Add(ClassInfo.GetFullName(param.Type)); ParamTypeKinds.Add("TypeKind." + param.Type.TypeKind.ToString()); ReturnParamNames.Add(param.Name); } else { if (param.Type.IsValueType && !SymbolTable.IsBasicType(param.Type) && !CsDslTranslater.IsImplementationOfSys(param.Type, "IEnumerator")) { string ns = ClassInfo.GetNamespaces(param.Type); if (SymbolTable.Instance.IsCs2DslSymbol(param.Type)) { ValueParams.Add(ParamNames.Count); NeedFuncInfo = true; } else if (ns != "System") { ExternValueParams.Add(ParamNames.Count); NeedFuncInfo = true; } } ParamNames.Add(param.Name); ParamTypes.Add(ClassInfo.GetFullName(param.Type)); ParamTypeKinds.Add("TypeKind." + param.Type.TypeKind.ToString()); } if (first && sym.IsExtensionMethod && sym.IsGenericMethod) { //扩展方法的泛型参数放在第一个参数后 foreach (var tp in sym.TypeParameters) { ParamNames.Add(tp.Name); if (tp.ConstraintTypes.Length > 0) { ParamTypes.Add(ClassInfo.GetFullName(tp.ConstraintTypes[0])); } else if (tp.HasReferenceTypeConstraint) { ParamTypes.Add("System.Object"); } else if (tp.HasValueTypeConstraint) { ParamTypes.Add("System.ValueType"); } else { ParamTypes.Add("null"); } ParamTypeKinds.Add("TypeKind." + tp.TypeKind.ToString()); } } first = false; } if (!sym.ReturnsVoid) { string returnType = ClassInfo.GetFullName(sym.ReturnType); if (returnType.StartsWith("System.Collections") && (sym.ReturnType.Name == "IEnumerable" || sym.ReturnType.Name == "IEnumerator")) { var analysis = new YieldAnalysis(); analysis.Visit(node); ExistYield = analysis.YieldCount > 0; } } ReturnValueCount = ReturnParamNames.Count + (sym.ReturnsVoid ? 0 : 1); }
internal bool IsCs2DslSymbol(IEventSymbol sym) { return(sym.ContainingAssembly == m_AssemblySymbol && !m_ExternTypes.ContainsKey(ClassInfo.SpecialGetFullTypeName(sym.ContainingType, true))); }
internal void Init(IMethodSymbol sym, SemanticModel model) { MethodSymbol = sym; Model = model; Args.Clear(); DslToObjectArgs.Clear(); ArgConversions.Clear(); DefaultValueArgs.Clear(); DslToObjectDefArgs.Clear(); ReturnArgs.Clear(); ReturnValueArgFlags.Clear(); ReturnArgOperations.Clear(); ReturnArgSymbols.Clear(); GenericTypeArgs.Clear(); ClassKey = ClassInfo.GetFullName(sym.ContainingType); GenericClassKey = ClassInfo.GetFullNameWithTypeParameters(sym.ContainingType); IsEnumClass = sym.ContainingType.TypeKind == TypeKind.Enum || ClassKey == "System.Enum"; IsExtensionMethod = sym.IsExtensionMethod; IsBasicValueMethod = SymbolTable.IsBasicValueMethod(sym); IsArrayStaticMethod = ClassKey == "System.Array" && sym.IsStatic; IsExternMethod = !SymbolTable.Instance.IsCs2DslSymbol(sym); if ((ClassKey == "UnityEngine.GameObject" || ClassKey == "UnityEngine.Component") && (sym.Name.StartsWith("GetComponent") || sym.Name.StartsWith("AddComponent"))) { IsComponentGetOrAdd = true; } NonGenericMethodSymbol = null; PostPositionGenericTypeArgs = false; ExternOverloadedMethodSignature = string.Empty; if (IsExternMethod) { var syms = sym.ContainingType.GetMembers(sym.Name); if (sym.IsGenericMethod) { bool existNonGenericVersion = false; if (null != syms) { //寻找匹配的非泛型版本 foreach (var isym in syms) { var msym = isym as IMethodSymbol; if (null != msym && !msym.IsGenericMethod && msym.Parameters.Length == sym.Parameters.Length + sym.TypeParameters.Length) { existNonGenericVersion = true; for (int i = 0; i < sym.TypeParameters.Length; ++i) { var psym = msym.Parameters[i]; if (psym.Type.Name != "Type") { existNonGenericVersion = false; break; } } for (int i = 0; i < sym.Parameters.Length; ++i) { var psym1 = msym.Parameters[i + sym.TypeParameters.Length]; var psym2 = sym.Parameters[i]; if (psym1.Type.Name != psym2.Type.Name && psym2.OriginalDefinition.Type.TypeKind != TypeKind.TypeParameter) { existNonGenericVersion = false; break; } } if (existNonGenericVersion) { NonGenericMethodSymbol = msym; PostPositionGenericTypeArgs = false; } else { existNonGenericVersion = true; for (int i = 0; i < sym.Parameters.Length; ++i) { var psym1 = msym.Parameters[i]; var psym2 = sym.Parameters[i]; if (psym1.Type.Name != psym2.Type.Name && psym2.OriginalDefinition.Type.TypeKind != TypeKind.TypeParameter) { existNonGenericVersion = false; break; } } for (int i = 0; i < sym.TypeParameters.Length; ++i) { var psym = msym.Parameters[i + sym.Parameters.Length]; if (psym.Type.Name != "Type") { existNonGenericVersion = false; break; } } if (existNonGenericVersion) { NonGenericMethodSymbol = msym; PostPositionGenericTypeArgs = true; } } if (existNonGenericVersion) { break; } } } if (!existNonGenericVersion) { //寻找匹配的变参版本 foreach (var isym in syms) { var msym = isym as IMethodSymbol; if (null != msym && !msym.IsGenericMethod && msym.Parameters.Length > 0 && msym.Parameters.Length <= sym.Parameters.Length) { bool existParamsVersion = true; var lastPsym = msym.Parameters[msym.Parameters.Length - 1]; if (lastPsym.IsParams) { for (int i = 0; i < msym.Parameters.Length; ++i) { var psym1 = msym.Parameters[i]; var psym2 = sym.Parameters[i]; if (i < msym.Parameters.Length - 1 && psym1.Type.Name != psym2.Type.Name) { existParamsVersion = false; break; } } } if (existParamsVersion) { NonGenericMethodSymbol = msym; break; } } } } } if (existNonGenericVersion) { foreach (var arg in sym.TypeArguments) { GenericTypeArgs.Add(arg); } } else { //没有找到参数匹配的非泛型版本,则不传递泛型参数类型 //这样处理可以适应2类可能有效的情形: //1、如果有多个重载函数,其中有一个object类型变参,则其他泛型参数版本会适配到这个非泛型变参版本 //2、有一些方法不需要明确传递泛型参数类型(比如普通实参可推导出泛型参数类型并且泛型参数类型在函数中不明确使用) } } if (null != syms) { int mcount = 0; if (sym.MethodKind == MethodKind.Constructor && sym.ContainingType.IsValueType) { //值类型构造总是按重载处理,默认构造总是会生成 mcount = 2; } else { foreach (var isym in syms) { var msym = isym as IMethodSymbol; if (msym.Parameters.Length == 0) { if (msym.Name == "GetType") { continue; } if (msym.Name == "GetHashCode") { continue; } } var fn = ClassInfo.GetFullName(msym.ContainingType); if (null != msym && msym.IsStatic == sym.IsStatic && msym.DeclaredAccessibility == Accessibility.Public && !msym.IsImplicitlyDeclared && !msym.IsGenericMethod && !ClassInfo.HasAttribute(msym, "System.ObsoleteAttribute")) { bool existPointer = false; foreach (var partype in msym.Parameters) { if (partype.Type.TypeKind == TypeKind.Pointer) { existPointer = true; break; } } if (!existPointer) { ++mcount; } } } } if (mcount > 1) { ExternOverloadedMethodSignature = SymbolTable.CalcExternOverloadedMethodSignature(sym, NonGenericMethodSymbol); } } SymbolTable.Instance.TryAddExternReference(sym); if (!sym.ReturnsVoid) { SymbolTable.Instance.TryAddExternReference(sym.ReturnType); } foreach (var p in sym.Parameters) { if (p.Kind != SymbolKind.TypeParameter) { SymbolTable.Instance.TryAddExternReference(p.Type); } } } else if (sym.IsGenericMethod) { foreach (var arg in sym.TypeArguments) { GenericTypeArgs.Add(arg); } } if (sym.IsGenericMethod) { foreach (var t in sym.TypeArguments) { if (t.TypeKind != TypeKind.TypeParameter) { SymbolTable.Instance.TryAddExternReference(t); } } } }
private void Init(IMethodSymbol sym) { MethodSymbol = sym; TypeChecker.CheckInvocation(sym, CallerMethodSymbol); Args.Clear(); ArgConversions.Clear(); ReturnArgs.Clear(); GenericTypeArgs.Clear(); ClassKey = ClassInfo.GetFullName(sym.ContainingType); GenericClassKey = ClassInfo.GetFullNameWithTypeParameters(sym.ContainingType); IsEnumClass = sym.ContainingType.TypeKind == TypeKind.Enum || ClassKey == "System.Enum"; IsExtensionMethod = sym.IsExtensionMethod; IsBasicValueMethod = SymbolTable.IsBasicValueMethod(sym); IsArrayStaticMethod = ClassKey == "System.Array" && sym.IsStatic; IsExternMethod = !SymbolTable.Instance.IsCs2DslSymbol(sym); if ((ClassKey == "UnityEngine.GameObject" || ClassKey == "UnityEngine.Component") && (sym.Name.StartsWith("GetComponent") || sym.Name.StartsWith("AddComponent"))) { IsComponentGetOrAdd = true; } NonGenericMethodSymbol = null; PostPositionGenericTypeArgs = false; if (sym.IsGenericMethod) { bool existNonGenericVersion = !IsExternMethod; var ctype = sym.ContainingType; var syms = ctype.GetMembers(sym.Name); if (null != syms) { foreach (var isym in syms) { var msym = isym as IMethodSymbol; if (null != msym && !msym.IsGenericMethod && msym.Parameters.Length == sym.Parameters.Length + sym.TypeParameters.Length) { existNonGenericVersion = true; for (int i = 0; i < sym.TypeParameters.Length; ++i) { var psym = msym.Parameters[i]; if (psym.Type.Name != "Type") { existNonGenericVersion = false; break; } } for (int i = 0; i < sym.Parameters.Length; ++i) { var psym1 = msym.Parameters[i + sym.TypeParameters.Length]; var psym2 = sym.Parameters[i]; if (psym1.Type.Name != psym2.Type.Name && psym2.OriginalDefinition.Type.TypeKind != TypeKind.TypeParameter) { existNonGenericVersion = false; break; } } if (existNonGenericVersion) { NonGenericMethodSymbol = msym; PostPositionGenericTypeArgs = false; } else { existNonGenericVersion = true; for (int i = 0; i < sym.Parameters.Length; ++i) { var psym1 = msym.Parameters[i]; var psym2 = sym.Parameters[i]; if (psym1.Type.Name != psym2.Type.Name && psym2.OriginalDefinition.Type.TypeKind != TypeKind.TypeParameter) { existNonGenericVersion = false; break; } } for (int i = 0; i < sym.TypeParameters.Length; ++i) { var psym = msym.Parameters[i + sym.Parameters.Length]; if (psym.Type.Name != "Type") { existNonGenericVersion = false; break; } } if (existNonGenericVersion) { NonGenericMethodSymbol = msym; PostPositionGenericTypeArgs = true; } } if (existNonGenericVersion) { break; } } } } if (existNonGenericVersion) { foreach (var arg in sym.TypeArguments) { GenericTypeArgs.Add(arg); } } } ExternOverloadedMethodSignature = string.Empty; if (IsExternMethod) { var syms = sym.ContainingType.GetMembers(sym.Name); if (null != syms) { int mcount = 0; foreach (var isym in syms) { var msym = isym as IMethodSymbol; var fn = ClassInfo.GetFullName(msym.ContainingType); if (null != msym && msym.IsStatic == sym.IsStatic && msym.DeclaredAccessibility == Accessibility.Public && !msym.IsImplicitlyDeclared && !msym.IsGenericMethod) { ++mcount; } } if (mcount > 1) { ExternOverloadedMethodSignature = SymbolTable.CalcOverloadedMethodSignature(sym, NonGenericMethodSymbol); } } } }
internal void OutputInvocation(StringBuilder codeBuilder, CsDslTranslater cs2dsl, ExpressionSyntax exp, bool isMemberAccess, SemanticModel model, SyntaxNode node) { IMethodSymbol sym = MethodSymbol; string mname = GetMethodName(); string prestr = string.Empty; bool externReturnStruct = IsExternMethod && !sym.ReturnsVoid && sym.ReturnType.IsValueType && !SymbolTable.IsBasicType(sym.ReturnType); if (externReturnStruct) { cs2dsl.MarkNeedFuncInfo(); } if (isMemberAccess) { string fnOfIntf = string.Empty; var expOper = model.GetOperationEx(exp); bool isExplicitInterfaceInvoke = cs2dsl.CheckExplicitInterfaceAccess(sym, ref fnOfIntf); bool expIsBasicType = false; if (!sym.IsStatic && null != expOper && SymbolTable.IsBasicType(expOper.Type)) { expIsBasicType = true; } if (sym.MethodKind == MethodKind.DelegateInvoke) { var memberAccess = node as MemberAccessExpressionSyntax; if (null != memberAccess) { var symInfo = model.GetSymbolInfoEx(node); var masym = symInfo.Symbol as ISymbol; if (null != masym) { bool isCs2Lua = SymbolTable.Instance.IsCs2DslSymbol(masym); string kind = SymbolTable.Instance.GetSymbolKind(masym); string fn = ClassInfo.GetFullName(masym.ContainingType); string dt = ClassInfo.GetFullName(sym); if (externReturnStruct) { codeBuilder.Append("callexterndelegationreturnstruct(getinstance(SymbolKind."); } else if (isCs2Lua) { codeBuilder.AppendFormat("call{0}delegation(getinstance(SymbolKind.", IsExternMethod ? "extern" : string.Empty); } else { codeBuilder.AppendFormat("call{0}delegation(getexterninstance(SymbolKind.", IsExternMethod ? "extern" : string.Empty); } codeBuilder.Append(kind); codeBuilder.Append(", "); cs2dsl.OutputExpressionSyntax(exp); codeBuilder.AppendFormat(", {0}, \"{1}\"), \"{2}\"", fn, memberAccess.Name, dt); prestr = ", "; } else { //error; } } else { //error; } } else if (isExplicitInterfaceInvoke) { //这里不区分是否外部符号了,委托到动态语言的脚本库实现,可根据对象运行时信息判断 if (externReturnStruct) { codeBuilder.Append("callexterninstancereturnstruct("); } else { codeBuilder.Append("callinstance("); } cs2dsl.OutputExpressionSyntax(exp); codeBuilder.Append(", "); codeBuilder.Append(ClassKey); codeBuilder.Append(", "); codeBuilder.AppendFormat("\"{0}\"", fnOfIntf); prestr = ", "; } else if (IsExtensionMethod) { if (externReturnStruct) { codeBuilder.Append("callexternextensionreturnstruct("); } else if (IsExternMethod) { codeBuilder.Append("callexternextension("); } else { codeBuilder.Append("callextension("); } codeBuilder.AppendFormat("{0}, \"{1}\", ", ClassKey, mname); cs2dsl.OutputExpressionSyntax(exp); prestr = ", "; } else if (IsBasicValueMethod || expIsBasicType) { //这里不区分是否外部符号了,委托到动态语言的脚本库实现,可根据对象运行时信息判断 string ckey = CalcInvokeTarget(IsEnumClass, ClassKey, cs2dsl, expOper); codeBuilder.Append("invokeforbasicvalue("); cs2dsl.OutputExpressionSyntax(exp); codeBuilder.Append(", "); codeBuilder.AppendFormat("{0}, {1}, \"{2}\"", IsEnumClass ? "true" : "false", ckey, mname); prestr = ", "; } else if (IsArrayStaticMethod) { //这里不区分是否外部符号了,委托到动态语言的脚本库实现,可根据对象运行时信息判断 codeBuilder.Append("invokearraystaticmethod("); if (null == FirstRefArray) { codeBuilder.Append("null, "); } else { cs2dsl.OutputExpressionSyntax(FirstRefArray); codeBuilder.Append(", "); } if (null == SecondRefArray) { codeBuilder.Append("null, "); } else { cs2dsl.OutputExpressionSyntax(SecondRefArray); codeBuilder.Append(", "); } codeBuilder.AppendFormat("\"{0}\"", mname); prestr = ", "; } else { if (sym.IsStatic) { if (externReturnStruct) { codeBuilder.Append("callexternstaticreturnstruct("); } else if (IsExternMethod) { codeBuilder.Append("callexternstatic("); } else { codeBuilder.Append("callstatic("); } codeBuilder.Append(ClassKey); } else { if (externReturnStruct) { codeBuilder.Append("callexterninstancereturnstruct("); } else if (IsExternMethod) { codeBuilder.Append("callexterninstance("); } else { codeBuilder.Append("callinstance("); } cs2dsl.OutputExpressionSyntax(exp); codeBuilder.Append(", "); codeBuilder.Append(ClassKey); } codeBuilder.AppendFormat(", \"{0}\"", mname); prestr = ", "; } } else { if (sym.MethodKind == MethodKind.DelegateInvoke) { cs2dsl.OutputExpressionSyntax(exp); codeBuilder.Append("("); } else if (sym.IsStatic) { if (externReturnStruct) { codeBuilder.Append("callexternstaticreturnstruct("); } else if (IsExternMethod) { codeBuilder.Append("callexternstatic("); } else { codeBuilder.Append("callstatic("); } codeBuilder.Append(ClassKey); codeBuilder.AppendFormat(", \"{0}\"", mname); prestr = ", "; } else { if (externReturnStruct) { codeBuilder.Append("callexterninstancereturnstruct("); } else if (IsExternMethod) { codeBuilder.Append("callexterninstance("); } else { codeBuilder.Append("callinstance("); } codeBuilder.Append("this"); codeBuilder.AppendFormat(", {0}, \"{1}\"", ClassKey, mname); prestr = ", "; } } if (Args.Count + DefaultValueArgs.Count + GenericTypeArgs.Count > 0) { codeBuilder.Append(prestr); } bool useTypeNameString = false; if (IsComponentGetOrAdd && SymbolTable.DslComponentByString) { var tArgs = sym.TypeArguments; if (tArgs.Length > 0 && SymbolTable.Instance.IsCs2DslSymbol(tArgs[0])) { useTypeNameString = true; } } TypeChecker.CheckInvocation(model, sym, Args, DefaultValueArgs, ArgConversions, CallerSyntaxNode, CallerMethodSymbol); cs2dsl.OutputArgumentList(this, useTypeNameString, node); codeBuilder.Append(")"); }
public override void VisitVariableDeclarator(VariableDeclaratorSyntax node) { var ci = m_ClassInfoStack.Peek(); var localSym = m_Model.GetDeclaredSymbol(node) as ILocalSymbol; if (null != localSym && localSym.HasConstantValue) { if (null != node.Initializer) { CodeBuilder.AppendFormat("{0}local({1}); {2}", GetIndentString(), node.Identifier.Text, node.Identifier.Text); } else { CodeBuilder.AppendFormat("{0}local({1})", GetIndentString(), node.Identifier.Text); } CodeBuilder.Append(" = "); OutputConstValue(localSym.ConstantValue, localSym); CodeBuilder.AppendLine(";"); return; } VisitLocalVariableDeclarator(ci, node); if (null != node.Initializer) { var oper = m_Model.GetOperation(node.Initializer.Value); if (null != oper && null != oper.Type && oper.Type.TypeKind == TypeKind.Struct && !CsDslTranslater.IsImplementationOfSys(oper.Type, "IEnumerator")) { if (SymbolTable.Instance.IsCs2DslSymbol(oper.Type)) { CodeBuilder.AppendFormat("{0}{1} = wrapstruct({2}, {3});", GetIndentString(), node.Identifier.Text, node.Identifier.Text, ClassInfo.GetFullName(oper.Type)); CodeBuilder.AppendLine(); } else { string ns = ClassInfo.GetNamespaces(oper.Type); if (ns != "System") { CodeBuilder.AppendFormat("{0}{1} = wrapexternstruct({2}, {3});", GetIndentString(), node.Identifier.Text, node.Identifier.Text, ClassInfo.GetFullName(oper.Type)); CodeBuilder.AppendLine(); } } } } }
private void BuildInterfaceInfo(INamedTypeSymbol typeSym, CSharpCompilation compilation, SymbolTable symTable) { foreach (var intf in typeSym.AllInterfaces) { if (!InterfaceSymbols.Contains(intf)) { InterfaceSymbols.Add(intf); } foreach (var sym in intf.GetMembers()) { var msym = sym as IMethodSymbol; if (null != msym) { var implSym = typeSym.FindImplementationForInterfaceMember(sym) as IMethodSymbol; if (null != implSym) { string name = symTable.NameMangling(msym); name = ClassInfo.CalcNameWithFullTypeName(name, sym.ContainingType); string implName = symTable.NameMangling(implSym); if (!InterfaceMethodMap.ContainsKey(name)) { InterfaceMethodMap.Add(name, implName); } } } var psym = sym as IPropertySymbol; if (null != psym && !psym.IsIndexer) { var implSym = typeSym.FindImplementationForInterfaceMember(sym) as IPropertySymbol; if (null != implSym && !psym.IsIndexer) { string name = SymbolTable.GetPropertyName(psym); name = ClassInfo.CalcNameWithFullTypeName(name, sym.ContainingType); string implName = SymbolTable.GetPropertyName(implSym); if (!InterfaceMethodMap.ContainsKey(name)) { InterfaceMethodMap.Add(name, implName); } } } var esym = sym as IEventSymbol; if (null != esym) { var implSym = typeSym.FindImplementationForInterfaceMember(sym) as IEventSymbol; if (null != implSym) { string name = SymbolTable.GetEventName(esym); name = ClassInfo.CalcNameWithFullTypeName(name, sym.ContainingType); string implName = SymbolTable.GetEventName(implSym); if (!InterfaceMethodMap.ContainsKey(name)) { InterfaceMethodMap.Add(name, implName); } } } } } if (typeSym.TypeKind != TypeKind.Interface) { foreach (var sym in typeSym.GetMembers()) { var msym = sym as IMethodSymbol; if (null != msym && msym.ExplicitInterfaceImplementations.Length > 0) { foreach (var implSym in msym.ExplicitInterfaceImplementations) { string fn = ClassInfo.GetFullName(implSym.ContainingType); ClassSymbolInfo csi; if (symTable.ClassSymbols.TryGetValue(fn, out csi)) { if (!csi.ExplicitInterfaceImplementationMethods.Contains(implSym)) csi.ExplicitInterfaceImplementationMethods.Add(implSym); } } } var psym = sym as IPropertySymbol; if (null != psym && !psym.IsIndexer && psym.ExplicitInterfaceImplementations.Length > 0) { foreach (var implSym in psym.ExplicitInterfaceImplementations) { string fn = ClassInfo.GetFullName(implSym.ContainingType); ClassSymbolInfo csi; if (symTable.ClassSymbols.TryGetValue(fn, out csi)) { if (!csi.ExplicitInterfaceImplementationProperties.Contains(implSym)) csi.ExplicitInterfaceImplementationProperties.Add(implSym); } } } var esym = sym as IEventSymbol; if (null != esym && esym.ExplicitInterfaceImplementations.Length > 0) { foreach (var implSym in esym.ExplicitInterfaceImplementations) { string fn = ClassInfo.GetFullName(implSym.ContainingType); ClassSymbolInfo csi; if (symTable.ClassSymbols.TryGetValue(fn, out csi)) { if (!csi.ExplicitInterfaceImplementationEvents.Contains(implSym)) csi.ExplicitInterfaceImplementationEvents.Add(implSym); } } } } } }
public override void VisitTryStatement(TryStatementSyntax node) { if (null != node.Block) { ClassInfo ci = m_ClassInfoStack.Peek(); MethodInfo mi = m_MethodInfoStack.Peek(); string srcPos = GetSourcePosForVar(node); string retVar = string.Format("__try_ret_{0}", srcPos); string retValVar = string.Format("__try_retval_{0}", srcPos); string handledVar = string.Format("__catch_handled_{0}", srcPos); string catchRetValVar = string.Format("__catch_retval_{0}", srcPos); mi.TryCatchUsingOrLoopSwitchStack.Push(true); ReturnContinueBreakAnalysis returnAnalysis0 = new ReturnContinueBreakAnalysis(); returnAnalysis0.RetValVar = retValVar; returnAnalysis0.Visit(node.Block); mi.TempReturnAnalysisStack.Push(returnAnalysis0); if (mi.IsAnonymousOrLambdaMethod) { //嵌入函数里的try块不能拆分成方法 CodeBuilder.AppendFormat("{0}local({1}, {2}); multiassign({1}, {2}) = dsltry({3}, {1}){{", GetIndentString(), retVar, retValVar, returnAnalysis0.ExistReturnInLoopOrSwitch ? "true" : "false"); CodeBuilder.AppendLine(); ++m_Indent; ++mi.TryUsingLayer; VisitBlock(node.Block); --mi.TryUsingLayer; --m_Indent; CodeBuilder.AppendFormat("{0}}};", GetIndentString()); CodeBuilder.AppendLine(); } else { //普通函数里的try块拆分成方法 var dataFlow = m_Model.AnalyzeDataFlow(node.Block); var ctrlFlow = m_Model.AnalyzeControlFlow(node.Block); List <string> inputs, outputs; string paramsStr; string outParamsStr = mi.CalcTryUsingFuncInfo(dataFlow, ctrlFlow, out inputs, out outputs, out paramsStr); returnAnalysis0.OutParamsStr = outParamsStr; string prestr = ", "; string tryFunc = string.Format("__try_func_{0}", srcPos); bool isStatic = mi.SemanticInfo.IsStatic; CodeBuilder.AppendFormat("{0}local({1}, {2}); multiassign({1}, {2}", GetIndentString(), retVar, retValVar); if (!string.IsNullOrEmpty(outParamsStr)) { CodeBuilder.Append(prestr); CodeBuilder.Append(outParamsStr); } CodeBuilder.AppendFormat(") = dsltryfunc({0}, {1}, {2}, {3}", retValVar, tryFunc, isStatic ? ci.Key : "this", dataFlow.DataFlowsOut.Length + (string.IsNullOrEmpty(mi.ReturnVarName) ? 1 : 2)); if (!string.IsNullOrEmpty(paramsStr)) { CodeBuilder.Append(prestr); CodeBuilder.Append(paramsStr); } CodeBuilder.AppendLine("){"); ++m_Indent; ++mi.TryUsingLayer; VisitBlock(node.Block); if (outputs.Count > 0 && ctrlFlow.ReturnStatements.Length <= 0) { //return(0)代表非try块里的返回语句 CodeBuilder.AppendFormat("{0}return(0", GetIndentString()); if (!string.IsNullOrEmpty(outParamsStr)) { CodeBuilder.Append(prestr); CodeBuilder.Append(outParamsStr); } CodeBuilder.AppendLine(");"); } --mi.TryUsingLayer; --m_Indent; CodeBuilder.AppendFormat("{0}}}options[{1}];", GetIndentString(), mi.CalcTryUsingFuncOptions(dataFlow, ctrlFlow, inputs, outputs)); CodeBuilder.AppendLine(); } mi.TempReturnAnalysisStack.Pop(); mi.TryCatchUsingOrLoopSwitchStack.Pop(); if (returnAnalysis0.Exist) { CodeBuilder.AppendFormat("{0}if({1}){{", GetIndentString(), retVar); CodeBuilder.AppendLine(); ++m_Indent; if (null != node.Finally) { VisitFinallyClause(node.Finally); } OutputTryCatchUsingReturn(returnAnalysis0, mi, retValVar); --m_Indent; CodeBuilder.AppendFormat("{0}}};", GetIndentString()); CodeBuilder.AppendLine(); } if (node.Catches.Count > 0) { CodeBuilder.AppendFormat("{0}local({1}, {2}); {1} = false;", GetIndentString(), handledVar, catchRetValVar); CodeBuilder.AppendLine(); foreach (var clause in node.Catches) { ReturnContinueBreakAnalysis returnAnalysis1 = new ReturnContinueBreakAnalysis(); returnAnalysis1.RetValVar = null;//catch块代码部分总是包装成一个函数对象 returnAnalysis1.Visit(clause.Block); mi.TempReturnAnalysisStack.Push(returnAnalysis1); CodeBuilder.AppendFormat("{0}{1} = dslcatch({2}, {3}, {4},", GetIndentString(), catchRetValVar, handledVar, retValVar, retVar); CodeBuilder.AppendLine(); ++m_Indent; ++mi.TryUsingLayer; VisitCatchClause(clause, handledVar); --mi.TryUsingLayer; --m_Indent; CodeBuilder.AppendFormat("{0});", GetIndentString()); CodeBuilder.AppendLine(); mi.TempReturnAnalysisStack.Pop(); if (returnAnalysis1.Exist) { if (null != node.Finally) { VisitFinallyClause(node.Finally); } OutputTryCatchUsingReturn(returnAnalysis1, mi, catchRetValVar); } } if (node.Catches.Count > 1) { if (SymbolTable.EnableTranslationCheck) { Logger.Instance.Log("Translation Warning", "try have multiple catch ! location: {0}", GetSourcePosForLog(node)); } } } if (null != node.Finally) { if (returnAnalysis0.Exist) { CodeBuilder.AppendFormat("{0}if(! {1}){{", GetIndentString(), retVar); CodeBuilder.AppendLine(); ++m_Indent; VisitFinallyClause(node.Finally); --m_Indent; CodeBuilder.AppendFormat("{0}}};", GetIndentString()); CodeBuilder.AppendLine(); } else { VisitFinallyClause(node.Finally); } } } }
private static string CalcFullName(ISymbol type, bool includeSelfName) { if (null == type) { return(string.Empty); } List <string> list = new List <string>(); if (includeSelfName) { //如果一个类标记为忽略,如果它是泛型类,则创建对象的名字使用泛型参数构建而不是实际类型参数构建 //这种类因为需要在脚本里手动实现,假定都是可以一个类实现泛型类的功能的。 //注意:由于这里是计算类型名称,使用命令行参数标记的忽略是没有效果(它使用名称来标记),此时仍然需要使用属性标记忽略的泛型类 bool ignore = ClassInfo.HasAttribute(type, "Cs2Dsl.IgnoreAttribute"); if (ignore) { list.Add(CalcNameWithTypeParameters(type)); } else { list.Add(CalcNameWithTypeArguments(type)); } } INamespaceSymbol ns = type.ContainingNamespace; var ct = type.ContainingType; string name = string.Empty; if (null != ct) { bool ignore = ClassInfo.HasAttribute(ct, "Cs2Dsl.IgnoreAttribute"); if (ignore) { name = CalcNameWithTypeParameters(ct); } else { name = CalcNameWithTypeArguments(ct); } } while (null != ct && name.Length > 0) { list.Insert(0, name); ns = ct.ContainingNamespace; ct = ct.ContainingType; if (null != ct) { bool ignore = ClassInfo.HasAttribute(ct, "Cs2Dsl.IgnoreAttribute"); if (ignore) { name = CalcNameWithTypeParameters(ct); } else { name = CalcNameWithTypeArguments(ct); } } else { name = string.Empty; } } while (null != ns && ns.Name.Length > 0) { list.Insert(0, ns.Name); ns = ns.ContainingNamespace; } return(string.Join(".", list.ToArray())); }