Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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.
        }
Пример #6
0
        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);
        }
Пример #7
0
        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}");
            }
        }
Пример #8
0
        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));
        }
Пример #9
0
        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);
        }
Пример #10
0
        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] = "";
        }
Пример #11
0
        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));
        }
Пример #12
0
        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});");
            }
        }