public override void VisitParameter(ParameterSyntax node) { var declaringMethodName = ".ctor"; var declaringMethodOrCtor = (BaseMethodDeclarationSyntax)node.Parent.Parent; var declaringType = declaringMethodOrCtor.ResolveDeclaringType(); if (node.Parent.Parent.IsKind(SyntaxKind.MethodDeclaration)) { var declaringMethod = (MethodDeclarationSyntax)declaringMethodOrCtor; declaringMethodName = declaringMethod.Identifier.ValueText; } var paramVar = TempLocalVar(node.Identifier.ValueText); Context.DefinitionVariables.RegisterNonMethod(string.Empty, node.Identifier.ValueText, MemberKind.Parameter, paramVar); var tbf = new MethodDefinitionVariable( declaringType.Identifier.Text, declaringMethodName, declaringMethodOrCtor.ParameterList.Parameters.Select(p => Context.GetTypeInfo(p.Type).Type.Name).ToArray()); var declaringMethodVariable = Context.DefinitionVariables.GetMethodVariable(tbf).VariableName; var exps = CecilDefinitionsFactory.Parameter(node, Context.SemanticModel, declaringMethodVariable, paramVar, ResolveType(node.Type)); AddCecilExpressions(exps); HandleAttributesInMemberDeclaration(node.AttributeLists, paramVar); base.VisitParameter(node); }
private string AddRemoveAccessor(EventFieldDeclarationSyntax node, string backingFieldVar, bool isStatic, SyntaxNode declaringType, string eventType) { if (node.Declaration.Variables.Count > 1) { throw new NotSupportedException($"Only one event per declaration is supported."); } var decl = node.Declaration.Variables[0]; var removeMethodVar = TempLocalVar($"{decl.Identifier.Text}_remove"); var isInterfaceDef = declaringType.IsKind(SyntaxKind.InterfaceDeclaration); var accessorModifiers = AccessModifiersForEventAccessors(node, isInterfaceDef); var removeMethodExps = CecilDefinitionsFactory.Method(Context, removeMethodVar, $"remove_{decl.Identifier.Text}", accessorModifiers, Context.TypeResolver.ResolvePredefinedType("Void"), Array.Empty <TypeParameterSyntax>()); var paramsExps = AddParameterTo(removeMethodVar, eventType); removeMethodExps = removeMethodExps.Concat(paramsExps); if (!isInterfaceDef) { var localVarsExps = CreateLocalVarsForAddMethod(removeMethodVar, backingFieldVar); var bodyExps = RemoveMethodBody(node, backingFieldVar, removeMethodVar, node.Declaration.Type, isStatic); removeMethodExps = removeMethodExps.Concat(bodyExps).Concat(localVarsExps); } foreach (var exp in removeMethodExps) { WriteCecilExpression(Context, exp); } return(removeMethodVar); }
private IEnumerable <string> HandleFieldDeclaration(MemberDeclarationSyntax node, VariableDeclarationSyntax variableDeclarationSyntax, SyntaxTokenList modifiers, BaseTypeDeclarationSyntax declaringType) { var declaringTypeVar = Context.DefinitionVariables.GetLastOf(MemberKind.Type).VariableName; var fieldDefVars = new List <string>(variableDeclarationSyntax.Variables.Count); var type = ResolveType(variableDeclarationSyntax.Type); var fieldType = ProcessRequiredModifiers(modifiers, type) ?? type; var fieldAttributes = MapAttributes(modifiers); foreach (var field in variableDeclarationSyntax.Variables) { var fieldVar = MethodExtensions.LocalVariableNameFor("fld", declaringType.Identifier.ValueText, field.Identifier.ValueText.CamelCase()); fieldDefVars.Add(fieldVar); var exps = CecilDefinitionsFactory.Field(declaringTypeVar, fieldVar, field.Identifier.ValueText, fieldType, fieldAttributes); AddCecilExpressions(exps); HandleAttributesInMemberDeclaration(node.AttributeLists, fieldVar); Context.DefinitionVariables.RegisterNonMethod(declaringType.Identifier.Text, field.Identifier.ValueText, MemberKind.Field, fieldVar); } return(fieldDefVars); }
public override void VisitEnumDeclaration(EnumDeclarationSyntax node) { _memberCollector = new EnumMemberValueCollector(); node.Accept(_memberCollector); var enumType = TempLocalVar(node.Identifier.ValueText); var attrs = ModifiersToCecil("TypeAttributes", node.Modifiers, "Private"); var typeDef = CecilDefinitionsFactory.Type(Context, enumType, node.Identifier.ValueText, attrs + " | TypeAttributes.Sealed", Context.TypeResolver.Resolve("System.Enum"), false, Array.Empty <string>()); AddCecilExpressions(typeDef); using (Context.DefinitionVariables.WithCurrent(node.Parent.IsKind(SyntaxKind.CompilationUnit) ? "" : node.Parent.ResolveDeclaringType().Identifier.ValueText, node.Identifier.ValueText, MemberKind.Type, enumType)) { //.class private auto ansi MyEnum //TODO: introduce TypeSystem.CoreLib.Enum/Action/etc... var fieldVar = MethodExtensions.LocalVariableNameFor("valueField", node.Identifier.ValueText); var valueFieldExp = CecilDefinitionsFactory.Field(enumType, fieldVar, "value__", "assembly.MainModule.TypeSystem.Int32", "FieldAttributes.SpecialName | FieldAttributes.RTSpecialName | FieldAttributes.Public"); AddCecilExpressions(valueFieldExp); HandleAttributesInMemberDeclaration(node.AttributeLists, enumType); base.VisitEnumDeclaration(node); } }
public override void VisitIndexerDeclaration(IndexerDeclarationSyntax node) { var propertyType = ResolveType(node.Type); var propertyDeclaringTypeVar = Context.DefinitionVariables.GetLastOf(MemberKind.Type).VariableName; var propName = "Item"; AddDefaultMemberAttribute(propertyDeclaringTypeVar, propName); var propDefVar = AddPropertyDefinition(propName, propertyType); var paramsVar = new List <string>(); foreach (var parameter in node.ParameterList.Parameters) { var paramVar = TempLocalVar(parameter.Identifier.ValueText); paramsVar.Add(paramVar); var exps = CecilDefinitionsFactory.Parameter(parameter, Context.SemanticModel, propDefVar, paramVar, ResolveType(parameter.Type)); AddCecilExpressions(exps); } ProcessPropertyAccessors(node, propertyDeclaringTypeVar, propName, propertyType, propDefVar, paramsVar); AddCecilExpression($"{propertyDeclaringTypeVar}.Properties.Add({propDefVar});"); HandleAttributesInMemberDeclaration(node.AttributeLists, TargetDoesNotMatch, SyntaxKind.FieldKeyword, propDefVar); // Normal property attrs HandleAttributesInMemberDeclaration(node.AttributeLists, TargetMatches, SyntaxKind.FieldKeyword, backingFieldVar); // [field: attr], i.e, attr belongs to the backing field. }
private string HandleTypeDeclaration(TypeDeclarationSyntax node, string baseType) { var varName = LocalVariableNameForId(NextLocalVariableTypeId()); var isStructWithNoFields = node.Kind() == SyntaxKind.StructDeclaration && node.Members.Count == 0; var typeDefinitionExp = CecilDefinitionsFactory.Type( Context, varName, node.Identifier.ValueText, TypeModifiersToCecil(node), baseType, isStructWithNoFields, ImplementedInterfacesFor(node.BaseList).Select(i => Context.TypeResolver.Resolve(i)), node.TypeParameterList); AddCecilExpressions(typeDefinitionExp); if (baseType != null) { // we postpone setting the base type because it may depend on generic parameters defined in the class itself (for instance 'class C<T> : Base<T> {}') // and these are introduced by the code in CecilDefinitionsFactory.Type(). WriteCecilExpression(Context, $"{varName}.BaseType = {ProcessBase(node)};"); } EnsureCurrentTypeHasADefaultCtor(node, varName); HandleAttributesInMemberDeclaration(node.AttributeLists, varName); Context.WriteCecilExpression(Environment.NewLine); return(varName); }
public static void AddMethodDefinition(IVisitorContext context, string methodVar, string fqName, string methodModifiers, string returnType, IList <TypeParameterSyntax> typeParameters) { context[methodVar] = ""; var exps = CecilDefinitionsFactory.Method(context, methodVar, fqName, methodModifiers, returnType, typeParameters); foreach (var exp in exps) { context.WriteCecilExpression($"{exp}{NewLine}"); } }
private string ResolveTypeArgument(ITypeSymbol typeArg) { if (typeArg is ITypeParameterSymbol typeParameterSymbol && Context.TypeResolver.ResolveTypeLocalVariable(typeArg.Name) == null) { // We need to forward "declare" the variable.... return(CecilDefinitionsFactory.GenericParameter(Context, $"tv_{typeParameterSymbol.Name}_{typeParameterSymbol.Ordinal}", typeArg.Name, "", typeParameterSymbol)); } return(Context.TypeResolver.Resolve(typeArg)); }
public override void VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node) { // Adds a field like: // .field public static literal valuetype xxx.MyEnum Second = int32(1) var enumMemberValue = _memberCollector[node]; var enumVarDef = Context.DefinitionVariables.GetLastOf(MemberKind.Type); var fieldVar = MethodExtensions.LocalVariableNameFor($"em_{enumVarDef.MemberName}_{NextLocalVariableId()}", node.Identifier.ValueText); var exp = CecilDefinitionsFactory.Field(enumVarDef.VariableName, fieldVar, node.Identifier.ValueText, enumVarDef.VariableName, "FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.Public | FieldAttributes.HasDefault", $"Constant = {enumMemberValue}"); AddCecilExpressions(exp); HandleAttributesInMemberDeclaration(node.AttributeLists, fieldVar); base.VisitEnumMemberDeclaration(node); }
internal void DefaultCtorInjector(string typeDefVar, BaseTypeDeclarationSyntax declaringClass) { var ctorMethodDefinitionExp = CecilDefinitionsFactory.Constructor(Context, out var ctorLocalVar, declaringClass.Identifier.ValueText, DefaultCtorAccessibilityFor(declaringClass), Array.Empty <string>()); AddCecilExpression(ctorMethodDefinitionExp); AddCecilExpression($"{typeDefVar}.Methods.Add({ctorLocalVar});"); var ctorBodyIL = TempLocalVar("il"); AddCecilExpression($@"var {ctorBodyIL} = {ctorLocalVar}.Body.GetILProcessor();"); AddCilInstruction(ctorBodyIL, OpCodes.Ldarg_0); AddCilInstruction(ctorBodyIL, OpCodes.Call, ResolveDefaultCtorFor(typeDefVar, declaringClass)); AddCilInstruction(ctorBodyIL, OpCodes.Ret); Context[ctorLocalVar] = ""; }
private IEnumerable <string> AddMethodBody(EventFieldDeclarationSyntax node, string backingFieldVar, string addMethodVar, TypeSyntax eventType, bool isStatic) { var(ldfld, ldflda) = isStatic ? (OpCodes.Ldsfld, OpCodes.Ldsflda) : (OpCodes.Ldfld, OpCodes.Ldflda); var combineMethod = Utils.ImportFromMainModule("typeof(Delegate).GetMethods().Single(m => m.Name == \"Combine\" && m.IsStatic && m.GetParameters().Length == 2)"); var compareExchangeExps = CompareExchangeMethodResolvingExps(backingFieldVar, out var compExcVar); var fieldVar = MakeGenericTypeIfAppropriate(node, backingFieldVar); // static member access does not have a *this* so simply replace with *Nop* var lgarg_0 = isStatic ? OpCodes.Nop : OpCodes.Ldarg_0; var bodyExps = CecilDefinitionsFactory.MethodBody(addMethodVar, new[] { lgarg_0, ldfld.WithOperand(fieldVar), OpCodes.Stloc_0, OpCodes.Ldloc_0.WithInstructionMarker("LoopStart"), OpCodes.Stloc_1, OpCodes.Ldloc_1, OpCodes.Ldarg.WithOperand(isStatic ? "0" : "1"), OpCodes.Call.WithOperand(combineMethod), OpCodes.Castclass.WithOperand(ResolveType(eventType)), OpCodes.Stloc_2, lgarg_0, ldflda.WithOperand(fieldVar), OpCodes.Ldloc_2, OpCodes.Ldloc_1, OpCodes.Call.WithOperand(compExcVar), OpCodes.Stloc_0, OpCodes.Ldloc_0, OpCodes.Ldloc_1, OpCodes.Bne_Un_S.WithBranchOperand("LoopStart"), OpCodes.Nop, OpCodes.Ret }); return(compareExchangeExps.Concat(bodyExps)); }
public override void VisitDelegateDeclaration(DelegateDeclarationSyntax node) { var typeVar = LocalVariableNameForId(NextLocalVariableTypeId()); var accessibility = ModifiersToCecil("TypeAttributes", node.Modifiers, "Private"); var typeDef = CecilDefinitionsFactory.Type( Context, typeVar, node.Identifier.ValueText, DefaultTypeAttributeFor(node).AppendModifier(accessibility), Context.TypeResolver.Resolve("System.MulticastDelegate"), false, Array.Empty <string>(), node.TypeParameterList, "IsAnsiClass = true"); AddCecilExpressions(typeDef); HandleAttributesInMemberDeclaration(node.AttributeLists, typeVar); using (Context.DefinitionVariables.WithCurrent("", node.Identifier.ValueText, MemberKind.Type, typeVar)) { // Delegate ctor AddCecilExpression(CecilDefinitionsFactory.Constructor(Context, out var ctorLocalVar, node.Identifier.Text, "MethodAttributes.FamANDAssem | MethodAttributes.Family", new[] { "System.Object", "System.IntPtr" }, "IsRuntime = true")); AddCecilExpression($"{ctorLocalVar}.Parameters.Add(new ParameterDefinition({Context.TypeResolver.ResolvePredefinedType("Object")}));"); AddCecilExpression($"{ctorLocalVar}.Parameters.Add(new ParameterDefinition({Context.TypeResolver.ResolvePredefinedType("IntPtr")}));"); AddCecilExpression($"{typeVar}.Methods.Add({ctorLocalVar});"); AddDelegateMethod(typeVar, "Invoke", ResolveType(node.ReturnType), node.ParameterList.Parameters, (methodVar, param) => CecilDefinitionsFactory.Parameter(param, Context.SemanticModel, methodVar, TempLocalVar($"{param.Identifier.ValueText}"), ResolveType(param.Type))); // BeginInvoke() method var beginInvokeMethodVar = TempLocalVar("beginInvoke"); AddCecilExpression( $@"var {beginInvokeMethodVar} = new MethodDefinition(""BeginInvoke"", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, {Context.TypeResolver.Resolve("System.IAsyncResult")}) {{ HasThis = true, IsRuntime = true, }};" ); foreach (var param in node.ParameterList.Parameters) { var paramExps = CecilDefinitionsFactory.Parameter(param, Context.SemanticModel, beginInvokeMethodVar, TempLocalVar($"{param.Identifier.ValueText}"), ResolveType(param.Type)); AddCecilExpressions(paramExps); } AddCecilExpression($"{beginInvokeMethodVar}.Parameters.Add(new ParameterDefinition({Context.TypeResolver.Resolve("System.AsyncCallback")}));"); AddCecilExpression($"{beginInvokeMethodVar}.Parameters.Add(new ParameterDefinition({Context.TypeResolver.ResolvePredefinedType("Object")}));"); AddCecilExpression($"{typeVar}.Methods.Add({beginInvokeMethodVar});"); AddDelegateMethod(typeVar, "EndInvoke", ResolveType(node.ReturnType), node.ParameterList.Parameters, (methodVar, param) => CecilDefinitionsFactory.Parameter(param, Context.SemanticModel, methodVar, TempLocalVar("ar"), Context.TypeResolver.Resolve("System.IAsyncResult"))); base.VisitDelegateDeclaration(node); } void AddDelegateMethod(string typeLocalVar, string methodName, string returnTypeName, in SeparatedSyntaxList <ParameterSyntax> parameters, Func <string, ParameterSyntax, IEnumerable <string> > paramterHandler) { var methodLocalVar = TempLocalVar(methodName.ToLower()); AddCecilExpression( $@"var {methodLocalVar} = new MethodDefinition(""{methodName}"", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, {returnTypeName}) {{ HasThis = true, IsRuntime = true, }};" ); foreach (var param in parameters) { AddCecilExpressions(paramterHandler(methodLocalVar, param)); } AddCecilExpression($"{typeLocalVar}.Methods.Add({methodLocalVar});"); } }