private JsClass GetJsClass(ITypeDefinition typeDefinition) { JsClass result; if (!_types.TryGetValue(typeDefinition, out result)) { if (typeDefinition.Kind == TypeKind.Struct && !_allowUserDefinedStructs) { var oldRegion = _errorReporter.Region; _errorReporter.Region = typeDefinition.Region; _errorReporter.Message(Messages._7998, "user-defined value type (struct)"); _errorReporter.Region = oldRegion; } var semantics = _metadataImporter.GetTypeSemantics(typeDefinition); if (semantics.GenerateCode) { var unusableTypes = Utils.FindUsedUnusableTypes(typeDefinition.GetAllBaseTypes(), _metadataImporter).ToList(); if (unusableTypes.Count > 0) { foreach (var ut in unusableTypes) { var oldRegion = _errorReporter.Region; _errorReporter.Region = typeDefinition.Region; _errorReporter.Message(Messages._7500, ut.FullName, typeDefinition.FullName); _errorReporter.Region = oldRegion; } } result = new JsClass(typeDefinition); } else { result = null; } _types[typeDefinition] = result; } return result; }
private JsClass GetJsClass(ITypeDefinition typeDefinition) { JsClass result; if (!_types.TryGetValue(typeDefinition, out result)) { var semantics = _metadataImporter.GetTypeSemantics(typeDefinition); if (semantics.GenerateCode) { var errors = Utils.FindTypeUsageErrors(typeDefinition.GetAllBaseTypes(), _metadataImporter); if (errors.HasErrors) { var oldRegion = _errorReporter.Region; try { _errorReporter.Region = typeDefinition.Region; foreach (var ut in errors.UsedUnusableTypes) _errorReporter.Message(Messages._7500, ut.FullName, typeDefinition.FullName); foreach (var t in errors.MutableValueTypesBoundToTypeArguments) _errorReporter.Message(Messages._7539, t.FullName); } finally { _errorReporter.Region = oldRegion; } } result = new JsClass(typeDefinition); } else { result = null; } _types[typeDefinition] = result; } return result; }
public JsClass Clone() { var result = new JsClass(this.CSharpTypeDefinition) { UnnamedConstructor = this.UnnamedConstructor }; ((List<JsNamedConstructor>)result.NamedConstructors).AddRange(this.NamedConstructors); ((List<JsMethod>)result.InstanceMethods).AddRange(this.InstanceMethods); ((List<JsMethod>)result.StaticMethods).AddRange(this.StaticMethods); ((List<JsStatement>)result.StaticInitStatements).AddRange(this.StaticInitStatements); return result; }
public JsClass Clone() { var result = new JsClass(this.CSharpTypeDefinition) { UnnamedConstructor = this.UnnamedConstructor }; ((List <JsNamedConstructor>)result.NamedConstructors).AddRange(this.NamedConstructors); ((List <JsMethod>)result.InstanceMethods).AddRange(this.InstanceMethods); ((List <JsMethod>)result.StaticMethods).AddRange(this.StaticMethods); ((List <JsStatement>)result.StaticInitStatements).AddRange(this.StaticInitStatements); return(result); }
private JsType ConvertType(JsClass type) { if (type.InstanceMethods.Any(m => m.Name == "runTests")) { _errorReporter.Region = type.CSharpTypeDefinition.Region; _errorReporter.Message(MessageSeverity.Error, 7019, string.Format("The type {0} cannot define a method named 'runTests' because it has a [TestFixtureAttribute].", type.CSharpTypeDefinition.FullName)); return type; } var instanceMethods = new List<JsMethod>(); var tests = new List<Tuple<string, string, bool, int?, JsFunctionDefinitionExpression>>(); foreach (var method in type.InstanceMethods) { var testAttr = _attributeStore.AttributesFor(method.CSharpMember).GetAttribute<TestAttribute>(); if (testAttr != null) { if (!method.CSharpMember.IsPublic || !method.CSharpMember.ReturnType.IsKnownType(KnownTypeCode.Void) || ((IMethod)method.CSharpMember).Parameters.Count > 0 || ((IMethod)method.CSharpMember).TypeParameters.Count > 0) { _errorReporter.Region = method.CSharpMember.Region; _errorReporter.Message(MessageSeverity.Error, 7020, string.Format("Method {0}: Methods decorated with a [TestAttribute] must be public, non-generic, parameterless instance methods that return void.", method.CSharpMember.FullName)); } tests.Add(Tuple.Create(testAttr.Description ?? method.CSharpMember.Name, testAttr.Category, testAttr.IsAsync, testAttr.ExpectedAssertionCount >= 0 ? (int?)testAttr.ExpectedAssertionCount : null, method.Definition)); } else instanceMethods.Add(method); } var testInvocations = new List<JsExpression>(); foreach (var category in tests.GroupBy(t => t.Item2).Select(g => new { Category = g.Key, Tests = g.Select(x => new { Description = x.Item1, IsAsync = x.Item3, ExpectedAssertionCount = x.Item4, Function = x.Item5 }) }).OrderBy(x => x.Category)) { if (category.Category != null) testInvocations.Add(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("QUnit"), "module"), JsExpression.String(category.Category))); testInvocations.AddRange(category.Tests.Select(t => JsExpression.Invocation(JsExpression.Identifier(t.IsAsync ? "asyncTest" : "test"), t.ExpectedAssertionCount != null ? new JsExpression[] { JsExpression.String(t.Description), JsExpression.Number(t.ExpectedAssertionCount.Value), _runtimeLibrary.Bind(t.Function, JsExpression.This, DummyRuntimeContext.Instance) } : new JsExpression[] { JsExpression.String(t.Description), _runtimeLibrary.Bind(t.Function, JsExpression.This, DummyRuntimeContext.Instance) }))); } instanceMethods.Add(new JsMethod(null, "runTests", null, JsExpression.FunctionDefinition(new string[0], JsStatement.Block(testInvocations.Select(t => (JsStatement)t))))); var result = type.Clone(); result.InstanceMethods.Clear(); foreach (var m in instanceMethods) result.InstanceMethods.Add(m); return result; }
private void CompileAndAddFieldInitializerToType(JsClass jsClass, string fieldName, ITypeDefinition owningType, Expression initializer, bool isStatic) { if (isStatic) { jsClass.StaticInitStatements.AddRange(CreateMethodCompiler().CompileFieldInitializer(initializer.GetRegion(), JsExpression.MemberAccess(_runtimeLibrary.GetScriptType(owningType, TypeContext.UseStaticMember), fieldName), initializer)); } else { AddInstanceInitStatements(jsClass, CreateMethodCompiler().CompileFieldInitializer(initializer.GetRegion(), JsExpression.MemberAccess(JsExpression.This, fieldName), initializer)); } }
private void CompileAndAddAutoPropertyMethodsToType(JsClass jsClass, IProperty property, PropertyScriptSemantics options, string backingFieldName) { if (options.GetMethod != null && options.GetMethod.GenerateCode) { var compiled = CreateMethodCompiler().CompileAutoPropertyGetter(property, options, backingFieldName); AddCompiledMethodToType(jsClass, property.Getter, options.GetMethod, new JsMethod(property.Getter, options.GetMethod.Name, new string[0], compiled)); } if (options.SetMethod != null && options.SetMethod.GenerateCode) { var compiled = CreateMethodCompiler().CompileAutoPropertySetter(property, options, backingFieldName); AddCompiledMethodToType(jsClass, property.Setter, options.SetMethod, new JsMethod(property.Setter, options.SetMethod.Name, new string[0], compiled)); } }
private void CompileAndAddAutoEventMethodsToType(JsClass jsClass, EventDeclaration node, IEvent evt, EventScriptSemantics options, string backingFieldName) { if (options.AddMethod != null && options.AddMethod.GenerateCode) { var compiled = CreateMethodCompiler().CompileAutoEventAdder(evt, options, backingFieldName); AddCompiledMethodToType(jsClass, evt.AddAccessor, options.AddMethod, new JsMethod(evt.AddAccessor, options.AddMethod.Name, new string[0], compiled)); } if (options.RemoveMethod != null && options.RemoveMethod.GenerateCode) { var compiled = CreateMethodCompiler().CompileAutoEventRemover(evt, options, backingFieldName); AddCompiledMethodToType(jsClass, evt.RemoveAccessor, options.RemoveMethod, new JsMethod(evt.RemoveAccessor, options.RemoveMethod.Name, new string[0], compiled)); } }
private void AddInstanceInitStatements(JsClass jsClass, IEnumerable<JsStatement> statements) { List<JsStatement> l; if (!_instanceInitStatements.TryGetValue(jsClass, out l)) _instanceInitStatements[jsClass] = l = new List<JsStatement>(); l.AddRange(statements); }
private void AddCompiledMethodToType(JsClass jsClass, IMethod method, MethodScriptSemantics options, JsMethod jsMethod) { if ((options.Type == MethodScriptSemantics.ImplType.NormalMethod && method.IsStatic) || options.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) { jsClass.StaticMethods.Add(jsMethod); } else { jsClass.InstanceMethods.Add(jsMethod); } }
private void AddDefaultFieldInitializerToType(JsClass jsClass, string fieldName, IMember member, IType fieldType, ITypeDefinition owningType, bool isStatic) { if (isStatic) { jsClass.StaticInitStatements.AddRange(CreateMethodCompiler().CompileDefaultFieldInitializer(member.Region, JsExpression.Member(_runtimeLibrary.GetScriptType(owningType, TypeContext.UseStaticMember), fieldName), fieldType)); } else { AddInstanceInitStatements(jsClass, CreateMethodCompiler().CompileDefaultFieldInitializer(member.Region, JsExpression.Member(JsExpression.This, fieldName), fieldType)); } }
private List<JsStatement> TryGetInstanceInitStatements(JsClass jsClass) { List<JsStatement> l; if (_instanceInitStatements.TryGetValue(jsClass, out l)) return l; else return new List<JsStatement>(); }
private void MaybeCompileAndAddConstructorToType(JsClass jsClass, ConstructorDeclaration node, IMethod constructor, ConstructorScriptSemantics options) { if (options.GenerateCode) { var mc = CreateMethodCompiler(); var compiled = mc.CompileConstructor(node, constructor, TryGetInstanceInitStatements(jsClass), options); OnMethodCompiled(constructor, compiled, mc); AddCompiledConstructorToType(jsClass, constructor, options, compiled); } }
private JsClass GetJsClass(ITypeDefinition typeDefinition) { JsClass result; if (!_types.TryGetValue(typeDefinition, out result)) { var semantics = _metadataImporter.GetTypeSemantics(typeDefinition); if (semantics.GenerateCode) { var unusableTypes = Utils.FindUsedUnusableTypes(typeDefinition.GetAllBaseTypes(), _metadataImporter).ToList(); if (unusableTypes.Count > 0) { foreach (var ut in unusableTypes) { var oldRegion = _errorReporter.Region; _errorReporter.Region = typeDefinition.Region; _errorReporter.Message(7500, ut.FullName, typeDefinition.FullName); _errorReporter.Region = oldRegion; } result = new JsClass(typeDefinition, "X", ConvertClassType(typeDefinition.Kind), new string[0], null, null); } else { var baseTypes = typeDefinition.GetAllBaseTypes().Where(t => _runtimeLibrary.GetScriptType(t, TypeContext.GenericArgument) != null).ToList(); var baseClass = typeDefinition.Kind != TypeKind.Interface ? _runtimeLibrary.GetScriptType(baseTypes.Last(t => !t.GetDefinition().Equals(typeDefinition) && t.Kind == TypeKind.Class), TypeContext.Inheritance) : null; // NRefactory bug/feature: Interfaces are reported as having System.Object as their base type. var interfaces = baseTypes.Where(t => !t.GetDefinition().Equals(typeDefinition) && t.Kind == TypeKind.Interface).Select(t => _runtimeLibrary.GetScriptType(t, TypeContext.Inheritance)).Where(t => t != null).ToList(); var typeArgNames = semantics.IgnoreGenericArguments ? null : typeDefinition.TypeParameters.Select(a => _namer.GetTypeParameterName(a)).ToList(); result = new JsClass(typeDefinition, semantics.Name, ConvertClassType(typeDefinition.Kind), typeArgNames, baseClass, interfaces); } } else { result = null; } _types[typeDefinition] = result; } return result; }
private void CompileAndAddFieldInitializerToType(JsClass jsClass, string fieldName, ITypeDefinition owningType, Expression initializer, bool isStatic) { if (isStatic) { jsClass.StaticInitStatements.AddRange(CreateMethodCompiler().CompileFieldInitializer(initializer.GetRegion(), JsExpression.Member(_runtimeLibrary.InstantiateType(Utils.SelfParameterize(owningType), this), fieldName), initializer, owningType)); } else { AddInstanceInitStatements(jsClass, CreateMethodCompiler().CompileFieldInitializer(initializer.GetRegion(), JsExpression.Member(JsExpression.This, fieldName), initializer, owningType)); } }
private void AddDefaultFieldInitializerToType(JsClass jsClass, string fieldName, IMember member, IType fieldType, ITypeDefinition owningType, bool isStatic) { if (isStatic) { jsClass.StaticInitStatements.AddRange(CreateMethodCompiler().CompileDefaultFieldInitializer(member.Region, JsExpression.Member(_runtimeLibrary.InstantiateType(Utils.SelfParameterize(owningType), this), fieldName), fieldType, member.DeclaringTypeDefinition)); } else { AddInstanceInitStatements(jsClass, CreateMethodCompiler().CompileDefaultFieldInitializer(member.Region, JsExpression.Member(JsExpression.This, fieldName), fieldType, member.DeclaringTypeDefinition)); } }
public virtual IEnumerable<JsStatement> GetStaticInitStatements(JsClass type) { return _prev.GetStaticInitStatements(type); }
private void MaybeAddDefaultConstructorToType(JsClass jsClass, IMethod constructor) { var options = _metadataImporter.GetConstructorSemantics(constructor); if (options.GenerateCode) { var mc = CreateMethodCompiler(); var compiled = mc.CompileDefaultConstructor(constructor, TryGetInstanceInitStatements(jsClass), options); OnMethodCompiled(constructor, compiled, mc); AddCompiledConstructorToType(jsClass, constructor, options, compiled); } }
private void AddClassMembers(JsClass c, JsExpression typeRef, ICompilation compilation, List<JsStatement> stmts) { ICollection<JsMethod> instanceMethods; if (_metadataImporter.IsTestFixture(c.CSharpTypeDefinition)) { var tests = new List<Tuple<string, string, bool, int?, JsFunctionDefinitionExpression>>(); var instanceMethodList = new List<JsMethod>(); foreach (var m in c.InstanceMethods) { var td = (m.CSharpMember is IMethod ? _metadataImporter.GetTestData((IMethod)m.CSharpMember) : null); if (td != null) { tests.Add(Tuple.Create(td.Description, td.Category, td.IsAsync, td.ExpectedAssertionCount, m.Definition)); } else { instanceMethodList.Add(m); } } var testInvocations = new List<JsExpression>(); foreach (var category in tests.GroupBy(t => t.Item2).Select(g => new { Category = g.Key, Tests = g.Select(x => new { Description = x.Item1, IsAsync = x.Item3, ExpectedAssertionCount = x.Item4, Function = x.Item5 }) }).OrderBy(x => x.Category)) { if (category.Category != null) testInvocations.Add(JsExpression.Invocation(JsExpression.Identifier("module"), JsExpression.String(category.Category))); testInvocations.AddRange(category.Tests.Select(t => JsExpression.Invocation(JsExpression.Identifier(t.IsAsync ? "asyncTest" : "test"), t.ExpectedAssertionCount != null ? new JsExpression[] { JsExpression.String(t.Description), JsExpression.Number(t.ExpectedAssertionCount.Value), _runtimeLibrary.Bind(t.Function, JsExpression.This) } : new JsExpression[] { JsExpression.String(t.Description), _runtimeLibrary.Bind(t.Function, JsExpression.This) }))); } instanceMethodList.Add(new JsMethod(null, "runTests", null, JsExpression.FunctionDefinition(new string[0], new JsBlockStatement(testInvocations.Select(t => new JsExpressionStatement(t)))))); instanceMethods = instanceMethodList; } else { instanceMethods = c.InstanceMethods; } if (instanceMethods.Count > 0) { stmts.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, Prototype), JsExpression.ObjectLiteral(instanceMethods.Select(m => new JsObjectLiteralProperty(m.Name, m.Definition != null ? RewriteMethod(m) : JsExpression.Null)))))); } if (c.NamedConstructors.Count > 0) { stmts.AddRange(c.NamedConstructors.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, m.Name), m.Definition)))); stmts.Add(new JsExpressionStatement(c.NamedConstructors.Reverse().Aggregate((JsExpression)JsExpression.MemberAccess(typeRef, Prototype), (right, ctor) => JsExpression.Assign(JsExpression.MemberAccess(JsExpression.MemberAccess(typeRef, ctor.Name), Prototype), right)))); // This generates a statement like {C}.ctor1.prototype = {C}.ctor2.prototype = {C}.prototoype } stmts.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, m.Name), RewriteMethod(m))))); if (c.TypeArgumentNames.Count > 0) { if (c.ClassType == JsClass.ClassTypeEnum.Interface) { stmts.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterGenericInterfaceInstance), typeRef, new JsTypeReferenceExpression(compilation.MainAssembly, c.Name), JsExpression.ArrayLiteral(c.TypeArgumentNames.Select(JsExpression.Identifier)), JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(JsExpression.ArrayLiteral(c.ImplementedInterfaces)))))); } else { stmts.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterGenericClassInstance), typeRef, new JsTypeReferenceExpression(compilation.MainAssembly, c.Name), JsExpression.ArrayLiteral(c.TypeArgumentNames.Select(JsExpression.Identifier)), JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(c.BaseClass)), JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(JsExpression.ArrayLiteral(c.ImplementedInterfaces)))))); } } }
private void MaybeCompileAndAddMethodToType(JsClass jsClass, EntityDeclaration node, BlockStatement body, IMethod method, MethodScriptSemantics options) { if (options.GenerateCode) { var typeParamNames = options.IgnoreGenericArguments ? (IEnumerable<string>)new string[0] : method.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList(); JsMethod jsMethod; if (method.IsAbstract) { jsMethod = new JsMethod(method, options.Name, typeParamNames, null); } else { var compiled = CompileMethod(node, body, method, options); jsMethod = new JsMethod(method, options.Name, typeParamNames, compiled); } AddCompiledMethodToType(jsClass, method, options, jsMethod); } }
private JsStatement GenerateResourcesClass(JsClass c) { var fields = c.StaticInitStatements .OfType<JsExpressionStatement>() .Select(s => s.Expression) .OfType<JsBinaryExpression>() .Where(expr => expr.NodeType == ExpressionNodeType.Assign && expr.Left is JsMemberAccessExpression) .Select(expr => new { Name = ((JsMemberAccessExpression)expr.Left).Member, Value = expr.Right }); return new JsExpressionStatement(JsExpression.Assign(new JsTypeReferenceExpression(c.CSharpTypeDefinition.ParentAssembly, c.Name), JsExpression.ObjectLiteral(fields.Select(f => new JsObjectLiteralProperty(f.Name, f.Value))))); }
IEnumerable<JsStatement> IOOPEmulator.GetStaticInitStatements(JsClass type) { return GetStaticInitStatements(type); }
private void AddCompiledConstructorToType(JsClass jsClass, IMethod constructor, ConstructorScriptSemantics options, JsFunctionDefinitionExpression jsConstructor) { switch (options.Type) { case ConstructorScriptSemantics.ImplType.UnnamedConstructor: if (jsClass.UnnamedConstructor != null) { _errorReporter.Region = constructor.Region; _errorReporter.Message(7501, constructor.DeclaringType.FullName); } else { jsClass.UnnamedConstructor = jsConstructor; } break; case ConstructorScriptSemantics.ImplType.NamedConstructor: jsClass.NamedConstructors.Add(new JsNamedConstructor(options.Name, jsConstructor)); break; case ConstructorScriptSemantics.ImplType.StaticMethod: jsClass.StaticMethods.Add(new JsMethod(constructor, options.Name, new string[0], jsConstructor)); break; } }