private void GenerateMethods(TypeEmitter typeEmitter, List <EmittedProperty> emittedProperties) { var signatureGrouping = this.typeModel.Methods.GroupBy(x => x, MethodSignatureEqualityComparer.Instance); foreach (var methodsWithSignature in signatureGrouping) { if (methodsWithSignature.Count() > 1) { foreach (var method in methodsWithSignature) { method.IsExplicit = !method.IsDeclaredOn(this.typeModel); } } } foreach (var method in this.typeModel.Methods) { if (method.IsDisposeMethod) { typeEmitter.EmitDisposeMethod(method); } else { this.GenerateMethod(typeEmitter, emittedProperties, method); } } }
static public void EmitConstructor(TypeEmitter declaringType, MethodReference targetMethod) { var definition = new FunctorMethodEmitter(declaringType, ".ctor", declaringType.Assembly.TypeSystem.Void, MethodAttributes.Assembly | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); definition.EmitConstructorBody(targetMethod); }
/// <summary> /// Initializes a new instance of the <see cref="EventEmitter"/> class. /// </summary> /// <param name="parent">The parent.</param> /// <param name="evt">The evt.</param> public EventEmitter(TypeEmitter parent, EventReference evt) { Parent = parent; Target = evt as EventDefinition ?? evt.Resolve(); if (Target.AddMethod != null) { add = new MethodEmitter(parent, Target.AddMethod); } else { var existing = parent.Target.GetMethod($"add_{Target.Name}", parent.Context.Module.TypeSystem.Void, new[] { evt.EventType }, new GenericParameter[0]); if (existing != null) { Target.AddMethod = existing.Resolve(); add = new MethodEmitter(parent, Target.AddMethod); } } if (Target.RemoveMethod != null) { remove = new MethodEmitter(parent, Target.RemoveMethod); } else { var existing = parent.Target.GetMethod($"remove_{Target.Name}", parent.Context.Module.TypeSystem.Void, new[] { evt.EventType }, new GenericParameter[0]); if (existing != null) { Target.RemoveMethod = existing.Resolve(); remove = new MethodEmitter(parent, Target.RemoveMethod); } } }
static public void EmitAsDelegate(TypeEmitter declaringType, TypeReference delegateType, MethodReference targetMethod) { var definition = new FunctorMethodEmitter(declaringType, "AsDelegate", delegateType, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig); definition.EmitAsDelegate(delegateType, targetMethod); }
/// <summary> /// Creates a property which replaces a provided field, and implements the <c>get</c> and <c>set</c> methods. /// </summary> /// <param name="emitter">The type emitter.</param> /// <param name="field">The field.</param> /// <returns></returns> public PropertyEmitter CreateFieldProperty(TypeEmitter emitter, FieldDefinition field) { var variable = new Variable(field); var property = emitter.EmitProperty(field.Name, field.FieldType, field.IsStatic); var context = emitter.Context; field.Name = $"<{field.Name}>k__BackingField"; context.AddCompilerGenerated(field); context.AddNonSerialized(field); var getter = property.GetGetter(); var gil = getter.GetIL(); gil.Emit(Codes.Nop); gil.Emit(Codes.ThisIf(variable)); gil.Emit(Codes.Load(variable)); gil.Emit(Codes.Return); getter.Body.InitLocals = true; var setter = property.GetSetter(); var sil = setter.GetIL(); sil.Emit(Codes.Nop); sil.Emit(Codes.ThisIf(variable)); sil.Emit(Codes.Arg(field.IsStatic ? 0 : 1)); sil.Emit(Codes.Store(variable)); sil.Emit(Codes.Return); setter.Body.InitLocals = true; return(property); }
protected override CakeMethodAliasGenerator CreateGenerator() { var typeEmitter = new TypeEmitter(); var parameterEmitter = new ParameterEmitter(typeEmitter); return(new CakeMethodAliasGenerator(typeEmitter, parameterEmitter)); }
static public void EmitInvoke(TypeEmitter declaringType, MethodReference targetMethod) { var definition = new FunctorMethodEmitter(declaringType, "Invoke", targetMethod.GetReturnType(), MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig); definition.EmitInvokeBody(targetMethod); }
/// <summary> /// Creates a multi-singleton field used to retain an instance of an attribute. /// </summary> /// <param name="emitter">The type weaver.</param> /// <param name="attribute">The attribute.</param> /// <param name="member">The member.</param> /// <returns></returns> public Variable CreateAttributeMultiSingleton(TypeEmitter emitter, CustomAttribute attribute, MemberReference member) { var index = Interlocked.Increment(ref id); var type = attribute.AttributeType; var name = $"<{type.Name}${index}>k__Attribute"; var field = singletons.EmitField(name, type, toStatic: true, toPublic: true); var emit = singletons.GetStaticConstructor(); var il = emit.GetIL(); il.Emit(Codes.Nop); foreach (var arg in attribute.ConstructorArguments) { CreateAttributeParameter(emit, attribute, arg); } il.Emit(Codes.Create(attribute.Constructor)); il.Emit(Codes.Store(field)); foreach (var prop in attribute.Properties) { CreateAttributeProperty(emit, attribute, field, prop); } CreateAttributeRequirements(il, attribute, member, field, true); return(field); }
internal CodegenTestBase(AssemblyEmitter assembly, string className, bool bulkTesting) : base(!bulkTesting) { assemblyEmitter = assembly ?? CreateTempAssembly(); typeEmitter = new TypeEmitter(assemblyEmitter, className); methodEmitter = new MethodEmitter(typeEmitter, kEntryPointMethodName, assemblyEmitter.TypeSystem.Void, MethodAttributes.Static | MethodAttributes.Assembly); console = AssemblyRegistry.FindType(assemblyEmitter, "System.Console"); consoleWriteString = AssemblyRegistry.GetCompatibleMethod(assemblyEmitter, console, "Write", new[] { assemblyEmitter.TypeSystem.String }); consoleWriteLineParams = AssemblyRegistry.GetCompatibleMethod(assemblyEmitter, console, "WriteLine", new[] { assemblyEmitter.TypeSystem.String, new ArrayType(assemblyEmitter.TypeSystem.Object) }); ienumerableGetEnumerator = AssemblyRegistry.GetCompatibleMethod(assemblyEmitter, "System.Collections.IEnumerable", "GetEnumerator", new TypeReference[0]); ienumerator = AssemblyRegistry.FindType(assemblyEmitter, "System.Collections.IEnumerator"); ienumeratorMoveNext = AssemblyRegistry.GetCompatibleMethod(assemblyEmitter, ienumerator, "MoveNext", new TypeReference[0]); var ienumerableCurrent = AssemblyRegistry.GetProperty(ienumerator, "Current"); ienumeratorGetCurrent = AssemblyRegistry.GetPropertyGetter(assemblyEmitter, ienumerableCurrent); this.bulkTesting = bulkTesting; }
public void WeaveImplementation(TypeEmitter emitter, TypeDefinition implementType, TypeDefinition interfaceType, Variable field) { if (!implementType.Interfaces.Any(i => i.InterfaceType.FullName == interfaceType.FullName)) { throw new NotSupportedException($"Cannot implement attribute '{implementType.FullName}' as it does not implement '{interfaceType.FullName}'"); } if (emitter.Target.Interfaces.Any(i => i.InterfaceType.FullName == interfaceType.FullName)) { return; } emitter.Target.Interfaces.Add(new InterfaceImplementation(interfaceType.Import())); foreach (var method in interfaceType.Methods.Concat(interfaceType.Interfaces.Select(i => i.InterfaceType.Resolve()).SelectMany(i => i.Methods))) { WeaveImplementedMethod(emitter, field, method, interfaceType); } foreach (var property in interfaceType.Properties) { WeaveImplementedProperty(emitter, field, property, interfaceType); } foreach (var evt in interfaceType.Events) { WeaveImplementedEvent(emitter, field, evt, interfaceType); } }
public CakeScriptGenerator( IBufferedFileSystem fileSystem, ICakeEnvironment environment, IGlobber globber, ICakeConfiguration configuration, IScriptProcessor processor, IScriptAliasFinder aliasFinder, ICakeLog log, IEnumerable <ILoadDirectiveProvider> loadDirectiveProviders = null) { _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _environment = environment ?? throw new ArgumentNullException(nameof(environment)); _globber = globber ?? throw new ArgumentNullException(nameof(globber)); _log = log ?? throw new ArgumentNullException(nameof(log)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _processor = processor ?? throw new ArgumentNullException(nameof(processor)); _aliasFinder = aliasFinder ?? throw new ArgumentNullException(nameof(fileSystem)); _analyzer = new ScriptAnalyzer(_fileSystem, _environment, _log, loadDirectiveProviders); var typeEmitter = new TypeEmitter(); var parameterEmitter = new ParameterEmitter(typeEmitter); _methodGenerator = new CakeMethodAliasGenerator(typeEmitter, parameterEmitter); _propertyGenerator = new CakePropertyAliasGenerator(typeEmitter); }
public void Should_return_different_instance_for_anonymous_type_with_different_property_order() { var emitter = new TypeEmitter(); var type1 = emitter.EmitType(CreateAnonymousTypeInfo(("Q", typeof(int)), ("P", typeof(int)))); var type2 = emitter.EmitType(CreateAnonymousTypeInfo(("P", typeof(int)), ("Q", typeof(int)))); type1.ShouldNotBeSameAs(type2); }
public void Should_return_the_same_instance_for_anonymous_type_with_same_property_definition() { var emitter = new TypeEmitter(); var type1 = emitter.EmitType(CreateAnonymousTypeInfo(("P", typeof(int)))); var type2 = emitter.EmitType(CreateAnonymousTypeInfo(("P", typeof(int)))); type1.ShouldBeSameAs(type2); }
public CakeAliasGenerator() { var typeEmitter = new TypeEmitter(); var parameterEmitter = new ParameterEmitter(typeEmitter); _methodGenerator = new CakeMethodAliasGenerator(typeEmitter, parameterEmitter); _propertyGenerator = new CakePropertyAliasGenerator(typeEmitter); }
public void Should_emity_anonymous_type_as_open_generic_type() { var o = new { P = default(string) }; var emitter = new TypeEmitter(); var type = emitter.EmitType(new TypeInfo(o.GetType())); type.IsGenericTypeDefinition.ShouldBeTrue(); type.ShouldNotBe(o.GetType().GetGenericTypeDefinition()); }
/// <summary> /// Weaves the constructor interceptors. /// </summary> public void WeaveConstructorInterceptors() { var candidates = Context.Candidates.FindTypeByConstructorInterceptors(); foreach (var item in candidates) { var weaver = new TypeEmitter(ModuleDefinition, item.Type, Context); WeaveConstructorInterceptors(weaver, item.Constructors); } }
/// <summary> /// Weaves an implementation of a property against the provided type. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="field">The attribute field.</param> /// <param name="property">The property.</param> /// <param name="interfaceType">The type of the interface.</param> public void WeaveImplementedProperty(TypeEmitter emitter, Variable field, PropertyDefinition property, TypeDefinition interfaceType) { var emitted = emitter.EmitProperty(property.Name, property.PropertyType.Import(), toBackingField: true); var implemented = field.Type.GetProperty(property.Name, property.PropertyType)?.Resolve(); if (implemented == null) { implemented = field.Type.GetProperty($"{interfaceType.FullName}.{property.Name}", returnType: property.PropertyType)?.Resolve(); if (implemented == null) { throw new MissingMemberException($"Cannot implement '{field.Type.FullName}' as it does not implement property '{property.Name}'"); } } var source = new PropertyEmitter(emitter, implemented); if (source.HasGetter && !emitted.HasGetter) { var getter = emitted.GetGetter(); var il = getter.GetIL(); var propertyGet = property.GetMethod?.Import() ?? implemented.GetMethod.Import(); getter.Body.SimplifyMacros(); il.Emit(Codes.Nop); il.Emit(Codes.ThisIf(field)); il.Emit(Codes.Cast(interfaceType)); il.Emit(Codes.Load(field)); il.Emit(Codes.Invoke(propertyGet.GetGeneric())); il.Emit(Codes.Return); getter.Body.OptimizeMacros(); getter.Body.InitLocals = true; } if (source.HasSetter && !emitted.HasSetter) { var setter = emitted.GetSetter(); var il = setter.GetIL(); var propertySet = property.SetMethod?.Import() ?? implemented.SetMethod.Import(); setter.Body.SimplifyMacros(); il.Emit(Codes.Nop); il.Emit(Codes.ThisIf(field)); il.Emit(Codes.Load(field)); il.Emit(Codes.Arg(setter.Target.IsStatic ? 0 : 1)); il.Emit(Codes.Invoke(propertySet.GetGeneric())); il.Emit(Codes.Return); setter.Body.OptimizeMacros(); setter.Body.InitLocals = true; } }
/// <summary> /// Creates the static container which will hold references to singleton values in order to keep types clean. /// </summary> public void InitializeStaticContainer() { var type = Context.Finder.ResolveType("Mimick.Runtime.SingletonContainer", full: true, throws: false)?.Resolve(); if (type == null) { type = new TypeDefinition("Mimick.Runtime", "SingletonContainer", ContainerTypeAttributes, TypeSystem.ObjectReference.Import()); ModuleDefinition.Types.Add(type); } singletons = new TypeEmitter(Context.Module, Context.Module.ImportReference(type), Context); }
public MethodEmitterBase(TypeEmitter declaringType, string name, TypeReference returnType, MethodAttributes methodAttributes) { DeclaringType = declaringType; methodDefinition = new MethodDefinition(name, methodAttributes, returnType); declaringType.AddMethod(methodDefinition); body = methodDefinition.Body; ilProcessor = body.GetILProcessor(); temporaryVariables = new TemporaryVariables(Assembly, body); Assembly.AddTypeUsage(returnType); }
public void Test_GetFieldFromBaseType() { var baseType = new TypeEmitter(assembly, "BaseType", "", TypeEmitter.DefaultTypeAttributes, assembly.TypeSystem.Object); var derivedType = new TypeEmitter(assembly, "DerivedType", "", TypeEmitter.DefaultTypeAttributes, baseType.Get(assembly)); var expectedField = new FieldDefinition("Field", FieldAttributes.Public, assembly.TypeSystem.Int32); baseType.AddField(expectedField); var actualField = AssemblyRegistry.GetField(assembly, derivedType, "Field"); Assert.AreEqual(expectedField, actualField); }
/// <summary> /// Creates an multi-instance-level field used to retain an instance of an attribute. /// </summary> /// <param name="emitter">The type weaver.</param> /// <param name="attribute">The attribute.</param> /// <param name="member">The member.</param> /// <returns></returns> public Variable CreateAttributeMultiInstanced(TypeEmitter emitter, CustomAttribute attribute, MemberReference member) { var index = Interlocked.Increment(ref id); var type = attribute.AttributeType; var name = $"<{type.Name}${index}>k__Attribute"; var existing = emitter.GetField(name, type, toStatic: false); if (existing != null) { return(existing); } var field = emitter.EmitField(name, type); foreach (var ctor in emitter.GetConstructors()) { var il = ctor.GetIL(); il.Insert = CodeInsertion.Before; il.Position = il.GetConstructorBaseOrThis()?.Next ?? il.GetFirst(); il.Emit(Codes.Nop); il.Emit(Codes.This); foreach (var arg in attribute.ConstructorArguments) { CreateAttributeParameter(ctor, attribute, arg); } il.Emit(Codes.Create(attribute.Constructor)); il.Emit(Codes.Store(field)); if (attribute.HasInterface(Context.Finder.IInstanceAware)) { il.Emit(Codes.ThisIf(field)); il.Emit(Codes.Load(field)); il.Emit(Codes.This); il.Emit(Codes.Invoke(Context.Finder.InstanceAwareInstanceSet)); } foreach (var prop in attribute.Properties) { CreateAttributeProperty(ctor, attribute, field, prop); } CreateAttributeRequirements(il, attribute, member, field, false); } return(field); }
private void GenerateMethod(TypeEmitter typeEmitter, List <EmittedProperty> emittedProperties, MethodModel method) { var methodEmitter = typeEmitter.EmitMethod(method); var serializationMethods = new ResolvedSerializationMethods(this.typeModel.SerializationMethodsAttribute?.Attribute, method.SerializationMethodsAttribute?.Attribute); if (method.RequestAttribute == null) { this.diagnostics.ReportMethodMustHaveRequestAttribute(method); } else { string?path = method.RequestAttribute.Attribute.Path; this.ValidatePathParams(method, path); this.ValidateCancellationTokenParams(method); this.ValidateMultipleBodyParams(method); this.ValidateHttpRequestMessageParams(method); methodEmitter.EmitRequestInfoCreation(method.RequestAttribute.Attribute); var resolvedAllowAnyStatusCode = method.AllowAnyStatusCodeAttribute ?? this.typeModel.TypeAllowAnyStatusCodeAttribute; if (resolvedAllowAnyStatusCode?.Attribute.AllowAnyStatusCode == true) { methodEmitter.EmitSetAllowAnyStatusCode(); } if (this.typeModel.BasePathAttribute?.Attribute.BasePath != null) { methodEmitter.EmitSetBasePath(this.typeModel.BasePathAttribute.Attribute.BasePath); } this.GenerateMethodProperties(methodEmitter, emittedProperties, serializationMethods); foreach (var methodHeader in method.HeaderAttributes) { if (methodHeader.Attribute.Name.Contains(":")) { this.diagnostics.ReportHeaderOnMethodMustNotHaveColonInName(method, methodHeader); } methodEmitter.EmitAddMethodHeader(methodHeader); } this.GenerateMethodParameters(methodEmitter, method, serializationMethods); if (!methodEmitter.TryEmitRequestMethodInvocation()) { this.diagnostics.ReportMethodMustHaveValidReturnType(method); } } }
/// <summary> /// Weaves all types which are candidates for property interception. /// </summary> public void WeavePropertyInterceptors() { var candidates = Context.Candidates.FindTypeByPropertyInterceptors(); foreach (var item in candidates) { var weaver = new TypeEmitter(Context.Module, item.Type, Context); foreach (var property in item.Properties) { WeavePropertyInterceptors(weaver, property); } } }
/// <summary> /// Weaves all implementations. /// </summary> public void WeaveImplementations() { var candidates = Context.Candidates.FindTypeByImplements(); foreach (var item in candidates) { var emitter = new TypeEmitter(ModuleDefinition, item.Type, Context); foreach (var attribute in item.Implements) { WeaveImplementation(emitter, attribute); } } }
private ClassNode(Parser parser, ContextNode parent, SequencePoint point) : base(parser, parent, point) { this.declaredMethods = new List <FunctionDeclarationNode>(); this.lambdas = new List <FunctionDeclarationNode>(); fields = new List <FieldDeclarationNode>(); globalImports = new List <Namespace>(); FullName = parser.Filename; emitter = new TypeEmitter(parser.Assembly, parser.Filename, parser.Namespace.Name); if (!string.IsNullOrEmpty(parser.Namespace.Name)) { globalImports.Add(parser.Namespace); } }
/// <summary> /// Weaves all types which are candidates for method interception. /// </summary> public void WeaveMethodInterceptors() { var candidates = Context.Candidates.FindTypeByMethodInterceptors(); foreach (var item in candidates) { var weaver = new TypeEmitter(Context.Module, item.Type, Context); foreach (var method in item.Methods) { var inner = new MethodEmitter(weaver, method.Method); WeaveMethodInterceptors(inner, method); } } }
public static TypeReference GetFunctorType(AssemblyEmitter assembly, TypeReference returnType, IReadOnlyList <TypeReference> arguments) { var name = TypeEmitter.ComputeNameFromReturnAndArgumentTypes(returnType, arguments); TypeDefinition value; if (instance.functorTypes.TryGetValue(name, out value)) { return(value); } value = FunctorBaseTypeEmitter.Create(assembly, returnType, arguments); instance.functorTypes.Add(name, value); assembly.AddType(value); return(MetadataHelpers.ScopeToAssembly(assembly, value)); }
private static void CheckAndRegenerate() { try { var scripts = MonoImporter.GetAllRuntimeMonoScripts().ToList(); var vmScripts = scripts.FindAll(p => TypeEmitter.Instance.ViewModelInterfaces.Contains(p.GetClass())); MD5 md5 = MD5.Create(); byte[] bytes = vmScripts .Select(p => AssetDatabase.GetAssetPath(p)) .Select(p => File.GetLastWriteTimeUtc(p)) .Select(p => p.Ticks) .SelectMany(p => BitConverter.GetBytes(p)) .ToArray(); byte[] hash = md5.ComputeHash(bytes); var newHashString = Convert.ToBase64String(hash); var oldHashString = EditorPrefs.GetString("MVVMD_hash", null); EditorPrefs.SetString("MVVMD_hash", newHashString); if (oldHashString != newHashString) { Debug.Log("MVVMDynamic: View models have changed. Regenerating sources..."); TypeEmitter.Instance.GenerateSources(); AssetDatabase.Refresh(); return; } bool allVmHaveSources = vmScripts .Select(p => p.GetClass()) .Select(p => TypeEmitter.GetDynamicallyGeneratedTypeName(p)) .All(p => scripts.Exists(s => s.name == p)); if (!allVmHaveSources) { Debug.Log("MVVMDynamic: View models sources not found. Regenerating sources..."); TypeEmitter.Instance.GenerateSources(); AssetDatabase.Refresh(); return; } } catch (Exception exception) { Debug.LogWarning("MVVMDynamic: Source generation failed"); Debug.LogException(exception); } }
/// <summary> /// Weaves all types which are candidates for field interception. /// </summary> public void WeaveFieldInterceptors() { var candidates = Context.Candidates.FindTypeByFieldInterceptors(); foreach (var item in candidates) { var weaver = new TypeEmitter(Context.Module, item.Type, Context); foreach (var field in item.Fields) { var replacement = WeaveFieldReplacements(weaver, field); var interceptor = new PropertyInterceptorInfo { Field = field.Field, Interceptors = field.Interceptors, Property = replacement }; WeavePropertyInterceptors(weaver, interceptor); } } }
public ConstructorEmitter(TypeEmitter declaringType, bool isStatic, MethodAttributes attributes) : base(declaringType, isStatic ? ".cctor" : ".ctor", declaringType.Assembly.TypeSystem.Void, attributes) { this.isStatic = isStatic; if (!isStatic && !declaringType.IsValueType) { var objectCtor = AssemblyRegistry.GetCompatibleMethod(declaringType.Assembly, declaringType.Assembly.TypeSystem.Object, ".ctor", new TypeReference[0]); Ldarg(0); Call(methodDefinition.DeclaringType, objectCtor); } Parsed = true; epilogue.Add(Instruction.Create(OpCodes.Ret)); AddEpilogue(); }