public void StringLiteralsAreCorrectlyEncoded() { AssertCorrect(JsExpression.String("x"), "'x'"); AssertCorrect(JsExpression.String("\""), "'\"'"); AssertCorrect(JsExpression.String("'"), "'\\''"); AssertCorrect(JsExpression.String("\r\n/\\"), "'\\r\\n/\\\\'"); }
private JsExpression CreateRegisterEnumCall(ITypeDefinition type, string name, JsExpression ctor) { var args = new List <JsExpression> { GetRoot(type), JsExpression.String(name), ctor }; var metadata = GetMetadataDescriptor(type, false); if (metadata != null) { args.Add(metadata); } return(JsExpression.Invocation(JsExpression.Member(_systemScript, RegisterEnum), args)); }
public JsStatement MakeInitAssemblyCall() { var args = new List <JsExpression> { _linker.CurrentAssemblyExpression, JsExpression.String(_compilation.MainAssembly.AssemblyName) }; var includedResources = GetIncludedResources().ToList(); if (includedResources.Count > 0) { args.Add(JsExpression.ObjectLiteral(includedResources.Select(r => new JsObjectLiteralProperty(r.Name, JsExpression.String(Convert.ToBase64String(ReadResource(r))))))); } return(JsExpression.Invocation(JsExpression.Member(_systemScript, InitAssembly), args)); }
public static JsExpression ConstructFieldPropertyAccessor(IMethod m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, string fieldName, Func <IType, JsExpression> instantiateType, bool isGetter, bool includeDeclaringType) { var properties = GetCommonMemberInfoProperties(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method))); properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(m.Parameters.Select(p => instantiateType(p.Type))))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(m.ReturnType))); properties.Add(new JsObjectLiteralProperty(isGetter ? "fget" : "fset", JsExpression.String(fieldName))); if (m.IsStatic) { properties.Add(new JsObjectLiteralProperty("isStatic", JsExpression.True)); } return(JsExpression.ObjectLiteral(properties)); }
public static IList <JsStatement> Process(IMetadataImporter metadataImporter, INamer namer, ICompilation compilation, IList <JsStatement> statements) { var usedSymbols = UsedSymbolsGatherer.Analyze(statements); var importer = new ImportVisitor(metadataImporter, namer, compilation.MainAssembly, usedSymbols); var body = statements.Select(s => importer.VisitStatement(s, null)).ToList(); var moduleDependencies = importer._moduleAliases.Concat(MetadataUtils.GetAdditionalDependencies(compilation.MainAssembly)); if (MetadataUtils.IsAsyncModule(compilation.MainAssembly)) { body.InsertRange(0, new[] { JsStatement.UseStrict, JsStatement.Var("exports", JsExpression.ObjectLiteral()) }); body.Add(JsStatement.Return(JsExpression.Identifier("exports"))); var pairs = new[] { new KeyValuePair <string, string>("mscorlib", namer.GetVariableName("_", usedSymbols)) } .Concat(moduleDependencies.OrderBy(x => x.Key)) .ToList(); body = new List <JsStatement> { JsExpression.Invocation( JsExpression.Identifier("define"), JsExpression.ArrayLiteral(pairs.Select(p => JsExpression.String(p.Key))), JsExpression.FunctionDefinition( pairs.Select(p => p.Value), JsStatement.Block(body) ) ) }; } else if (moduleDependencies.Any()) { // If we require any module, we require mscorlib. This should work even if we are a leaf module that doesn't include any other module because our parent script will do the mscorlib require for us. body.InsertRange(0, new[] { JsStatement.UseStrict, JsExpression.Invocation(JsExpression.Identifier("require"), JsExpression.String("mscorlib")) } .Concat(moduleDependencies .OrderBy(x => x.Key).OrderBy(x => x.Key) .Select(x => JsStatement.Var( x.Value, JsExpression.Invocation( JsExpression.Identifier("require"), JsExpression.String(x.Key)))) .ToList())); } else { body.Insert(0, JsStatement.UseStrict); body = new List <JsStatement> { JsExpression.Invocation(JsExpression.FunctionDefinition(new string[0], JsStatement.Block(body))) }; } return(body); }
private JsExpression CreateRegisterInterfaceCall(ITypeDefinition type, string name, JsExpression ctor, IList <JsExpression> interfaces) { var args = new List <JsExpression> { GetRoot(type), JsExpression.String(name), ctor }; var metadata = GetMetadataDescriptor(type, false); if (interfaces.Count > 0 || metadata != null) { args.Add(JsExpression.ArrayLiteral(interfaces)); } if (metadata != null) { args.Add(metadata); } return(JsExpression.Invocation(JsExpression.Member(_systemScript, RegisterInterface), args)); }
private static List <JsObjectLiteralProperty> GetCommonMemberInfoProperties(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType) { var result = new List <JsObjectLiteralProperty>(); var attr = GetScriptableAttributes(m.Attributes, metadataImporter).ToList(); if (attr.Count > 0) { result.Add(new JsObjectLiteralProperty("attr", JsExpression.ArrayLiteral(attr.Select(a => ConstructAttribute(a, m.DeclaringTypeDefinition, compilation, metadataImporter, namer, runtimeLibrary, errorReporter))))); } if (includeDeclaringType) { result.Add(new JsObjectLiteralProperty("typeDef", instantiateType(m.DeclaringType))); } result.Add(new JsObjectLiteralProperty("name", JsExpression.String(m.Name))); return(result); }
public void ModuleWithAdditionalDepenciesWorks() { var asm = Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new AdditionalDependencyAttribute("my-additional-dep", "myDep"), () => new AdditionalDependencyAttribute("my-other-dep", "myDep2") }); var actual = Process(new JsStatement[] { JsExpression.String("myModule") }, asm); AssertCorrect(actual, @"'use strict'; require('mscorlib'); var myDep = require('my-additional-dep'); var myDep2 = require('my-other-dep'); 'myModule'; "); }
public void AsyncModuleWithAdditionalDependenciesWorks() { var asm = Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new AsyncModuleAttribute(), () => new AdditionalDependencyAttribute("my-additional-dep", "__unused"), () => new AdditionalDependencyAttribute("my-other-dep", "myDep2") }); var actual = Process(new JsStatement[] { JsExpression.String("myModule") }, new[] { asm }); AssertCorrect(actual, @"define(['mscorlib', 'my-additional-dep', 'my-other-dep'], function($_, __unused, myDep2) { 'use strict'; var exports = {}; 'myModule'; return exports; }); "); }
private JsExpression CreateRegisterClassCall(JsExpression root, string name, JsExpression ctor, JsExpression baseClass, IList <JsExpression> interfaces) { var args = new List <JsExpression> { root, JsExpression.String(name), ctor }; if (baseClass != null) { args.Add(baseClass); } else if (interfaces.Count > 0) { args.Add(JsExpression.Null); } if (interfaces.Count > 0) { args.AddRange(interfaces); } return(JsExpression.Invocation(JsExpression.Member(_systemType, RegisterClass), args)); }
public static IList <JsStatement> Process(IScriptSharpMetadataImporter metadataImporter, INamer namer, IAssembly mainAssembly, IList <JsStatement> statements) { var usedSymbols = UsedSymbolsGatherer.Analyze(statements); var importer = new ImportVisitor(metadataImporter, namer, mainAssembly, usedSymbols); var body = statements.Select(s => importer.VisitStatement(s, null)).ToList(); if (metadataImporter.IsAsyncModule) { body.Insert(0, new JsVariableDeclarationStatement("exports", JsExpression.ObjectLiteral())); body.Add(new JsReturnStatement(JsExpression.Identifier("exports"))); var pairs = new[] { new KeyValuePair <string, string>("mscorlib", namer.GetVariableName("_", usedSymbols)) }.Concat(importer._moduleAliases.OrderBy(x => x.Key)).ToList(); body = new List <JsStatement> { new JsExpressionStatement( JsExpression.Invocation( JsExpression.Identifier("define"), JsExpression.ArrayLiteral(pairs.Select(p => JsExpression.String(p.Key))), JsExpression.FunctionDefinition( pairs.Select(p => p.Value), new JsBlockStatement(body) ) ) ) }; } else if (importer._moduleAliases.Count > 0) { // If we require any module, we require mscorlib. This should work even if we are a leaf module that doesn't include any other module because our parent script will do the mscorlib require for us. body.InsertRange(0, new[] { (JsStatement) new JsExpressionStatement(JsExpression.Invocation(JsExpression.Identifier("require"), JsExpression.String("mscorlib"))) } .Concat(importer._moduleAliases.OrderBy(x => x.Key) .Select(x => new JsVariableDeclarationStatement( x.Value, JsExpression.Invocation( JsExpression.Identifier("require"), JsExpression.String(x.Key)))) .ToList())); } return(body); }
public static JsExpression MakeConstantExpression(object value) { value = Utils.ConvertToDoubleOrStringOrBoolean(value); if (value is bool) { return((bool)value ? JsExpression.True : JsExpression.False); } else if (value is double) { return(JsExpression.Number((double)value)); } if (value is string) { return(JsExpression.String((string)value)); } else if (value == null) { return(JsExpression.Null); } else { throw new ArgumentException("value"); } }
public JsExpression GetExpressionForLocal(string name, JsExpression accessor, IType type, IRuntimeContext context) { var scriptType = TypeOf(type, context); JsExpression getterDefinition = JsExpression.FunctionDefinition(new string[0], JsStatement.Return(accessor)); JsExpression setterDefinition = JsExpression.FunctionDefinition(new[] { "$" }, JsExpression.Assign(accessor, JsExpression.Identifier("$"))); if (UsesThisVisitor.Analyze(accessor)) { getterDefinition = JsExpression.Invocation(JsExpression.Member(getterDefinition, "bind"), JsExpression.This); setterDefinition = JsExpression.Invocation(JsExpression.Member(setterDefinition, "bind"), JsExpression.This); } return(JsExpression.ObjectLiteral( new JsObjectLiteralProperty("ntype", JsExpression.Number((int)ExpressionType.MemberAccess)), new JsObjectLiteralProperty("type", scriptType), new JsObjectLiteralProperty("expression", JsExpression.ObjectLiteral( new JsObjectLiteralProperty("ntype", JsExpression.Number((int)ExpressionType.Constant)), new JsObjectLiteralProperty("type", scriptType), new JsObjectLiteralProperty("value", JsExpression.ObjectLiteral()) )), new JsObjectLiteralProperty("member", JsExpression.ObjectLiteral( new JsObjectLiteralProperty("typeDef", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Object).GetDefinition())), new JsObjectLiteralProperty("name", JsExpression.String(name)), new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property)), new JsObjectLiteralProperty("returnType", scriptType), new JsObjectLiteralProperty("getter", JsExpression.ObjectLiteral( new JsObjectLiteralProperty("typeDef", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Object).GetDefinition())), new JsObjectLiteralProperty("name", JsExpression.String("get_" + name)), new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method)), new JsObjectLiteralProperty("returnType", scriptType), new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral()), new JsObjectLiteralProperty("def", getterDefinition) )), new JsObjectLiteralProperty("setter", JsExpression.ObjectLiteral( new JsObjectLiteralProperty("typeDef", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Object).GetDefinition())), new JsObjectLiteralProperty("name", JsExpression.String("set_" + name)), new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method)), new JsObjectLiteralProperty("returnType", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Void).GetDefinition())), new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(scriptType)), new JsObjectLiteralProperty("def", setterDefinition) )) )) )); }
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, this) } : new JsExpression[] { JsExpression.String(t.Description), _runtimeLibrary.Bind(t.Function, JsExpression.This, this) }))); } 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); }
public IList <JsStatement> Process(IEnumerable <JsType> types, IMethod entryPoint) { var result = new List <JsStatement>(); var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList(); foreach (var t in orderedTypes) { try { string name = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name; bool isGlobal = string.IsNullOrEmpty(name); bool isMixin = MetadataUtils.IsMixin(t.CSharpTypeDefinition); result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName)); var typeRef = JsExpression.Identifier(_namer.GetTypeVariableName(name)); if (t is JsClass) { var c = (JsClass)t; if (isGlobal) { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(GetRoot(t.CSharpTypeDefinition, exportNonPublic: true), m.Name), m.Definition)))); } else if (isMixin) { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition)))); } else if (MetadataUtils.IsResources(c.CSharpTypeDefinition)) { result.Add(GenerateResourcesClass(c)); } else { var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement); if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList(); var stmts = new List <JsStatement> { new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor) }; AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), stmts); stmts.AddRange(c.StaticInitStatements); stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName))); var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName)); for (int i = 0; i < stmts.Count; i++) { stmts[i] = replacer.Process(stmts[i]); } result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(typeParameterNames, new JsBlockStatement(stmts)))); var args = new List <JsExpression> { GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount) }; var metadata = GetMetadataDescriptor(t.CSharpTypeDefinition, false); if (metadata != null) { args.Add(metadata); } result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterface : RegisterGenericClass), args))); } else { result.Add(new JsVariableDeclarationStatement(typeRef.Name, unnamedCtor)); AddClassMembers(c, typeRef, result); } } } else if (t is JsEnum) { var e = (JsEnum)t; result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement))); var values = new List <JsObjectLiteralProperty>(); foreach (var v in e.CSharpTypeDefinition.Fields) { if (v.ConstantValue != null) { var sem = _metadataImporter.GetFieldSemantics(v); if (sem.Type == FieldScriptSemantics.ImplType.Field) { values.Add(new JsObjectLiteralProperty(sem.Name, JsExpression.Number(Convert.ToDouble(v.ConstantValue)))); } else if (sem.Type == FieldScriptSemantics.ImplType.Constant && sem.Name != null) { values.Add(new JsObjectLiteralProperty(sem.Name, sem.Value is string?JsExpression.String((string)sem.Value) : JsExpression.Number(Convert.ToDouble(sem.Value)))); } } else { _errorReporter.Region = v.Region; _errorReporter.InternalError("Enum field " + v.FullName + " is not constant."); } } result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(values)))); } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } var typesToRegister = orderedTypes .Where(c => !(c is JsClass && MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) && !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) && (!MetadataUtils.IsResources(c.CSharpTypeDefinition) || c.CSharpTypeDefinition.IsExternallyVisible()) && // Resources classes are only exported if they are public. !MetadataUtils.IsMixin(c.CSharpTypeDefinition)) .ToList(); result.AddRange(TopologicalSortTypesByInheritance(typesToRegister) .Select(c => { try { string name = _metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name; if (c.CSharpTypeDefinition.Kind == TypeKind.Enum) { return(CreateRegisterEnumCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name)))); } if (MetadataUtils.IsResources(c.CSharpTypeDefinition)) { return(JsExpression.Invocation(JsExpression.Member(_systemScript, RegisterType), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name)))); } if (c.CSharpTypeDefinition.Kind == TypeKind.Interface) { return(CreateRegisterInterfaceCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name)), GetImplementedInterfaces(c.CSharpTypeDefinition.GetDefinition()).ToList())); } else { return(CreateRegisterClassCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name)), GetBaseClass(c.CSharpTypeDefinition), GetImplementedInterfaces(c.CSharpTypeDefinition).ToList())); } } catch (Exception ex) { _errorReporter.Region = c.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName); return(JsExpression.Number(0)); } }) .Select(expr => new JsExpressionStatement(expr))); result.AddRange(GetStaticInitializationOrder(orderedTypes.OfType <JsClass>(), 1) .Where(c => !MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter) && !MetadataUtils.IsResources(c.CSharpTypeDefinition)) .SelectMany(c => c.StaticInitStatements)); if (entryPoint != null) { if (entryPoint.Parameters.Count > 0) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7800, entryPoint.FullName); } else { var sem = _metadataImporter.GetMethodSemantics(entryPoint); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7801, entryPoint.FullName); } else { result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name)))); } } } return(result); }
private TypeOOPEmulationPhase CreateTypeDefinitions(JsType type) { string name = _metadataImporter.GetTypeSemantics(type.CSharpTypeDefinition).Name; bool isGlobal = string.IsNullOrEmpty(name); bool isMixin = MetadataUtils.IsMixin(type.CSharpTypeDefinition, _attributeStore); bool export = type.CSharpTypeDefinition.IsExternallyVisible(); var statements = new List <JsStatement>(); statements.Add(JsStatement.Comment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + type.CSharpTypeDefinition.FullName)); string typevarName = _namer.GetTypeVariableName(name); if (type is JsClass) { var c = (JsClass)type; if (isGlobal) { statements.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(JsExpression.Identifier(GetRoot(type.CSharpTypeDefinition)), m.Name), m.Definition))); export = false; } else if (isMixin) { statements.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition))); export = false; } else if (MetadataUtils.IsResources(c.CSharpTypeDefinition, _attributeStore)) { statements.Add(GenerateResourcesClass(c)); } else { var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock); if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList(); var stmts = new List <JsStatement> { JsStatement.Var(InstantiatedGenericTypeVariableName, unnamedCtor) }; AddClassMembers(c, InstantiatedGenericTypeVariableName, stmts); stmts.AddRange(c.StaticInitStatements); stmts.Add(JsStatement.Return(JsExpression.Identifier(InstantiatedGenericTypeVariableName))); var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName)); for (int i = 0; i < stmts.Count; i++) { stmts[i] = replacer.Process(stmts[i]); } statements.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(typeParameterNames, JsStatement.Block(stmts)))); statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name))); var args = new List <JsExpression> { JsExpression.Identifier(typevarName), _linker.CurrentAssemblyExpression, JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount) }; statements.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? InitGenericInterface : InitGenericClass), args)); } else { statements.Add(JsStatement.Var(typevarName, unnamedCtor)); statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name))); AddClassMembers(c, typevarName, statements); } } } else if (type is JsEnum) { var e = (JsEnum)type; statements.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock))); statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(e.CSharpTypeDefinition).Name))); } if (export) { string root = GetRoot(type.CSharpTypeDefinition); statements.Add(JsExpression.Assign(MakeNestedMemberAccess(name, JsExpression.Identifier(root)), JsExpression.Identifier(typevarName))); } return(new TypeOOPEmulationPhase(null, statements)); }
private static JsExpression ConstructMemberInfo(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType, MethodScriptSemantics semanticsIfAccessor) { if (m is IMethod && ((IMethod)m).IsConstructor) { return(ConstructConstructorInfo((IMethod)m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType)); } var properties = GetCommonMemberInfoProperties(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); if (m.IsStatic) { properties.Add(new JsObjectLiteralProperty("isStatic", JsExpression.True)); } if (m is IMethod) { var method = (IMethod)m; var sem = semanticsIfAccessor ?? metadataImporter.GetMethodSemantics(method); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7201, m.FullName, "method"); return(JsExpression.Null); } if ((sem.Type == MethodScriptSemantics.ImplType.NormalMethod || sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) && sem.ExpandParams) { properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True)); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method))); if (sem.Type == MethodScriptSemantics.ImplType.InlineCode) { var usedNames = new HashSet <string>(); var parameters = new List <IVariable>(); var variables = new Dictionary <IVariable, VariableData>(); var arguments = new List <ResolveResult>(); foreach (var p in method.Parameters) { string name = namer.GetVariableName(p.Name, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); arguments.Add(new LocalResolveResult(variable)); } var tokens = InlineCodeMethodCompiler.Tokenize(method, sem.LiteralCode, _ => {}); var compileResult = Compile(CreateMethodInvocationResolveResult(method, method.IsStatic ? (ResolveResult) new TypeResolveResult(method.DeclaringType) : new ThisResolveResult(method.DeclaringType), arguments), method.DeclaringTypeDefinition, method, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, true, variables, usedNames); var definition = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), JsStatement.Block(compileResult.AdditionalStatements.Concat(new[] { JsStatement.Return(compileResult.Expression) }))); if (tokens.Any(t => t.Type == InlineCodeToken.TokenType.TypeParameter && t.OwnerType == SymbolKind.Method)) { definition = JsExpression.FunctionDefinition(method.TypeParameters.Select(namer.GetTypeParameterName), JsStatement.Return(definition)); properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } properties.Add(new JsObjectLiteralProperty("def", definition)); } else { if (IsJsGeneric(method, metadataImporter)) { properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } if (sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) { properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True)); } properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(method.ReturnType))); properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(method.Parameters.Select(p => instantiateType(p.Type))))); } else if (m is IField) { var field = (IField)m; var sem = metadataImporter.GetFieldSemantics(field); if (sem.Type != FieldScriptSemantics.ImplType.Field) { errorReporter.Message(Messages._7201, m.FullName, "field"); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Field))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(field.ReturnType))); properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } else if (m is IProperty) { var prop = (IProperty)m; var sem = metadataImporter.GetPropertySemantics(prop); properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(prop.ReturnType))); if (prop.Parameters.Count > 0) { properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(prop.Parameters.Select(p => instantiateType(p.Type))))); } switch (sem.Type) { case PropertyScriptSemantics.ImplType.GetAndSetMethods: if (sem.GetMethod != null && sem.GetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.GetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.GetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "getter"); return(JsExpression.Null); } if (sem.SetMethod != null && sem.SetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.SetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.SetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "setter"); return(JsExpression.Null); } if (sem.GetMethod != null) { properties.Add(new JsObjectLiteralProperty("getter", ConstructMemberInfo(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.GetMethod))); } if (sem.SetMethod != null) { properties.Add(new JsObjectLiteralProperty("setter", ConstructMemberInfo(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.SetMethod))); } break; case PropertyScriptSemantics.ImplType.Field: if (prop.CanGet) { properties.Add(new JsObjectLiteralProperty("getter", ConstructFieldPropertyAccessor(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: true, includeDeclaringType: includeDeclaringType))); } if (prop.CanSet) { properties.Add(new JsObjectLiteralProperty("setter", ConstructFieldPropertyAccessor(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: false, includeDeclaringType: includeDeclaringType))); } properties.Add(new JsObjectLiteralProperty("fname", JsExpression.String(sem.FieldName))); break; default: errorReporter.Message(Messages._7201, m.FullName, "property"); return(JsExpression.Null); } } else if (m is IEvent) { var evt = (IEvent)m; var sem = metadataImporter.GetEventSemantics(evt); if (sem.Type != EventScriptSemantics.ImplType.AddAndRemoveMethods) { errorReporter.Message(Messages._7201, m.FullName, "event"); return(JsExpression.Null); } if (sem.AddMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.AddMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.AddMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "add accessor"); return(JsExpression.Null); } if (sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "remove accessor"); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Event))); properties.Add(new JsObjectLiteralProperty("adder", ConstructMemberInfo(evt.AddAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.AddMethod))); properties.Add(new JsObjectLiteralProperty("remover", ConstructMemberInfo(evt.RemoveAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.RemoveMethod))); } else { throw new ArgumentException("Invalid member " + m); } return(JsExpression.ObjectLiteral(properties)); }
public void ResourcesAttributeCausesAResourcesClassToBeGenerated() { AssertCorrect( @"//////////////////////////////////////////////////////////////////////////////// // SomeNamespace.InnerNamespace.MyClass var $SomeNamespace_InnerNamespace_MyClass = { Field1: 'the value', Field2: 123, Field3: null }; {Type}.registerType(global, 'SomeNamespace.InnerNamespace.MyClass', $SomeNamespace_InnerNamespace_MyClass); ", new MockScriptSharpMetadataImporter { IsResources = t => t.FullName == "SomeNamespace.InnerNamespace.MyClass" }, new JsClass(CreateMockTypeDefinition("SomeNamespace.InnerNamespace.MyClass"), JsClass.ClassTypeEnum.Class, null, null, new JsExpression[0]) { StaticInitStatements = { new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field1"), JsExpression.String("the value"))), new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field2"), JsExpression.Number(123))), new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field3"), JsExpression.Null)), } }); }
protected void AssertCorrect(string orig, string expected, MethodType methodType = MethodType.Normal) { int tempIndex = 0, stateIndex = 0, loopLabelIndex = 0; var stmt = JsBlockStatement.MakeBlock(JavaScriptParser.Parser.ParseStatement(orig)); JsBlockStatement result; if (methodType == MethodType.Iterator) { int finallyHandlerIndex = 0; result = StateMachineRewriter.RewriteIteratorBlock(stmt, e => e.NodeType != ExpressionNodeType.Identifier, () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture), () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture), () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)), () => string.Format("$finally" + (++finallyHandlerIndex).ToString(CultureInfo.InvariantCulture)), v => JsExpression.Invocation(JsExpression.Identifier("setCurrent"), v), sm => { var body = new List <JsStatement>(); if (sm.Variables.Count > 0) { body.Add(new JsVariableDeclarationStatement(sm.Variables)); } body.AddRange(sm.FinallyHandlers.Select(h => new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier(h.Item1), h.Item2)))); if (sm.Disposer != null) { body.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("dispose"), new JsFunctionDefinitionExpression(new string[0], sm.Disposer)))); } body.Add(sm.MainBlock); return(new JsBlockStatement(body)); }); } else if (methodType == MethodType.AsyncTask || methodType == MethodType.AsyncVoid) { result = StateMachineRewriter.RewriteAsyncMethod(stmt, e => e.NodeType != ExpressionNodeType.Identifier, () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture), () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture), () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)), "$sm", "$doFinally", methodType == MethodType.AsyncTask ? new JsVariableDeclaration("$tcs", JsExpression.New(JsExpression.Identifier("TaskCompletionSource"))) : null, expr => { if (methodType != MethodType.AsyncTask) { throw new InvalidOperationException("Should not set result in async void method"); } return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "setResult"), expr ?? JsExpression.String("<<null>>"))); }, expr => { if (methodType != MethodType.AsyncTask) { throw new InvalidOperationException("Should not set exception in async void method"); } return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "setException"), expr)); }, () => { if (methodType != MethodType.AsyncTask) { throw new InvalidOperationException("Should not get task async void method"); } return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "getTask"))); }, (sm, ctx) => JsExpression.Invocation(JsExpression.Identifier("$Bind"), sm, ctx)); } else { result = StateMachineRewriter.RewriteNormalMethod(stmt, e => e.NodeType != ExpressionNodeType.Identifier, () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture), () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture), () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture))); } var actual = OutputFormatter.Format(result); Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(expected.Replace("\r\n", "\n")), "Expected:\n" + expected + "\n\nActual:\n" + actual); }
public IList <JsStatement> Process(IEnumerable <JsType> types, IMethod entryPoint) { var result = new List <JsStatement>(); var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList(); var exportedNamespacesByRoot = new Dictionary <string, HashSet <string> >(); foreach (var t in orderedTypes) { try { string name = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name; bool isGlobal = string.IsNullOrEmpty(name); bool isMixin = MetadataUtils.IsMixin(t.CSharpTypeDefinition); bool export = t.CSharpTypeDefinition.IsExternallyVisible(); result.Add(JsStatement.Comment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName)); string typevarName = _namer.GetTypeVariableName(name); if (t is JsClass) { var c = (JsClass)t; if (isGlobal) { result.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(JsExpression.Identifier(GetRoot(t.CSharpTypeDefinition)), m.Name), m.Definition))); export = false; } else if (isMixin) { result.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition))); export = false; } else if (MetadataUtils.IsResources(c.CSharpTypeDefinition)) { result.Add(GenerateResourcesClass(c)); } else { var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock); if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList(); var stmts = new List <JsStatement> { JsStatement.Var(InstantiatedGenericTypeVariableName, unnamedCtor) }; AddClassMembers(c, InstantiatedGenericTypeVariableName, stmts); stmts.AddRange(c.StaticInitStatements); stmts.Add(JsStatement.Return(JsExpression.Identifier(InstantiatedGenericTypeVariableName))); var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName)); for (int i = 0; i < stmts.Count; i++) { stmts[i] = replacer.Process(stmts[i]); } result.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(typeParameterNames, JsStatement.Block(stmts)))); result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name))); var args = new List <JsExpression> { JsExpression.Identifier(typevarName), JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount) }; result.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? InitGenericInterface : InitGenericClass), args)); } else { result.Add(JsStatement.Var(typevarName, unnamedCtor)); result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name))); AddClassMembers(c, typevarName, result); } } } else if (t is JsEnum) { var e = (JsEnum)t; result.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock))); result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(e.CSharpTypeDefinition).Name))); } if (export) { string root = GetRoot(t.CSharpTypeDefinition); var split = SplitIntoNamespaceAndName(name); if (!string.IsNullOrEmpty(split.Item1)) { HashSet <string> hs; if (!exportedNamespacesByRoot.TryGetValue(root, out hs)) { hs = exportedNamespacesByRoot[root] = new HashSet <string>(); } hs.Add(split.Item1); } result.Add(JsExpression.Assign(MakeNestedMemberAccess(name, JsExpression.Identifier(root)), JsExpression.Identifier(typevarName))); } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } result.InsertRange(0, exportedNamespacesByRoot.OrderBy(x => x.Key).SelectMany(x => CreateNamespaces(JsExpression.Identifier(x.Key), x.Value)).ToList()); var typesToRegister = TopologicalSortTypesByInheritance(orderedTypes) .Where(c => !(c is JsClass && MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) && !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) && !MetadataUtils.IsResources(c.CSharpTypeDefinition) && !MetadataUtils.IsMixin(c.CSharpTypeDefinition)) .ToList(); foreach (var t in typesToRegister) { try { string name = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name; string typevarName = _namer.GetTypeVariableName(name); if (t.CSharpTypeDefinition.Kind == TypeKind.Enum) { result.Add(CreateInitEnumCall((JsEnum)t, typevarName)); } else { var c = (JsClass)t; if (t.CSharpTypeDefinition.Kind == TypeKind.Interface) { result.Add(CreateInitInterfaceCall(c, typevarName, GetImplementedInterfaces(t.CSharpTypeDefinition.GetDefinition()).ToList())); } else { result.Add(CreateInitClassCall(c, typevarName, GetBaseClass(t.CSharpTypeDefinition), GetImplementedInterfaces(t.CSharpTypeDefinition).ToList())); if (c.NamedConstructors.Count > 0) { result.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(_namer.GetTypeVariableName(name)))); } } } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } foreach (var t in orderedTypes) { var metadata = GetMetadataDescriptor(t.CSharpTypeDefinition, false); if (metadata != null) { result.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, SetMetadata), JsExpression.Identifier(_namer.GetTypeVariableName(_metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name)), metadata)); } } result.AddRange(GetStaticInitializationOrder(orderedTypes.OfType <JsClass>(), 1) .Where(c => !MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter) && !MetadataUtils.IsResources(c.CSharpTypeDefinition)) .SelectMany(c => c.StaticInitStatements)); if (entryPoint != null) { if (entryPoint.Parameters.Count > 0) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7800, entryPoint.FullName); } else { var sem = _metadataImporter.GetMethodSemantics(entryPoint); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7801, entryPoint.FullName); } else { result.Add(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name))); } } } return(result); }
public IList <JsStatement> Process(IEnumerable <JsType> types, ICompilation compilation, IMethod entryPoint) { var result = new List <JsStatement>(); var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList(); foreach (var t in orderedTypes) { try { string name = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name; bool isGlobal = string.IsNullOrEmpty(name); bool isMixin = _metadataImporter.IsMixin(t.CSharpTypeDefinition); result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName)); var typeRef = JsExpression.Identifier(_namer.GetTypeVariableName(name)); if (t is JsClass) { var c = (JsClass)t; if (isGlobal) { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(GetRoot(t.CSharpTypeDefinition, exportNonPublic: true), m.Name), m.Definition)))); } else if (isMixin) { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition)))); } else if (_metadataImporter.IsResources(t.CSharpTypeDefinition)) { result.Add(GenerateResourcesClass(c)); } else { var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement); if (c.TypeArgumentNames.Count == 0) { result.Add(new JsVariableDeclarationStatement(typeRef.Name, unnamedCtor)); AddClassMembers(c, typeRef, compilation, result); } else { var stmts = new List <JsStatement> { new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor) }; AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), compilation, stmts); stmts.AddRange(c.StaticInitStatements); stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName))); result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(c.TypeArgumentNames, new JsBlockStatement(stmts)))); result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemType, c.ClassType == JsClass.ClassTypeEnum.Interface ? RegisterGenericInterface : RegisterGenericClass), GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Number(c.TypeArgumentNames.Count)))); } } } else if (t is JsEnum) { var e = (JsEnum)t; bool flags = GetAttributePositionalArgs(t.CSharpTypeDefinition, FlagsAttribute, "System") != null; result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement))); result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(e.Values.Select(v => new JsObjectLiteralProperty(v.Name, (_metadataImporter.IsNamedValues(t.CSharpTypeDefinition) ? JsExpression.String(v.Name) : JsExpression.Number(v.Value)))))))); result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemType, RegisterEnum), GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Boolean(flags)))); } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } var typesToRegister = orderedTypes.OfType <JsClass>() .Where(c => c.TypeArgumentNames.Count == 0 && !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) && (!_metadataImporter.IsResources(c.CSharpTypeDefinition) || Utils.IsPublic(c.CSharpTypeDefinition)) && // Resources classes are only exported if they are public. !_metadataImporter.IsMixin(c.CSharpTypeDefinition)) .ToList(); result.AddRange(TopologicalSortTypesByInheritance(typesToRegister) .Select(c => { try { string name = _metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name; if (_metadataImporter.IsResources(c.CSharpTypeDefinition)) { return(JsExpression.Invocation(JsExpression.Member(_systemType, RegisterType), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name)))); } if (c.ClassType == JsClass.ClassTypeEnum.Interface) { return(JsExpression.Invocation(JsExpression.Member(_systemType, RegisterInterface), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name)), JsExpression.ArrayLiteral(c.ImplementedInterfaces))); } else { return(CreateRegisterClassCall(GetRoot(c.CSharpTypeDefinition), name, JsExpression.Identifier(_namer.GetTypeVariableName(name)), c.BaseClass, c.ImplementedInterfaces)); } } catch (Exception ex) { _errorReporter.Region = c.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName); return(JsExpression.Number(0)); } }) .Select(expr => new JsExpressionStatement(expr))); result.AddRange(orderedTypes.OfType <JsClass>().Where(c => c.TypeArgumentNames.Count == 0 && !_metadataImporter.IsResources(c.CSharpTypeDefinition)).SelectMany(t => t.StaticInitStatements)); if (entryPoint != null) { if (entryPoint.Parameters.Count > 0) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(7800, entryPoint.FullName); } else { var sem = _metadataImporter.GetMethodSemantics(entryPoint); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(7801, entryPoint.FullName); } else { result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name)))); } } } return(result); }
public static IList <string> ValidateLiteralCode(IMethod method, string literalCode, Func <string, JsExpression> resolveType, Func <IType, JsExpression> resolveTypeArgument) { var errors = new List <string>(); var tokens = Tokenize(method, literalCode, s => errors.Add("Error in literal code pattern: " + s)); if (tokens == null) { return(errors); } CompileInlineCodeMethodInvocation(method, tokens, method.IsStatic || method.IsConstructor ? null : JsExpression.Null, method.Parameters.Select(p => p.IsParams ? (JsExpression)JsExpression.ArrayLiteral() : JsExpression.String("X")).ToList(), resolveType, resolveTypeArgument, errors.Add); return(errors); }
public void ClassesWithModuleNamesGetExportedToTheExportsObject() { AssertCorrect( @"//////////////////////////////////////////////////////////////////////////////// // GenericClass var $GenericClass = function(T1) { var $type = function() { }; {Type}.registerGenericClassInstance($type, {GenericClass}, [T1], function() { return; }, function() { return []; }); return $type; }; {Type}.registerGenericClass(exports, 'GenericClass', $GenericClass, 1); //////////////////////////////////////////////////////////////////////////////// // GenericInterface var $GenericInterface = function(T1) { var $type = function() { }; {Type}.registerGenericInterfaceInstance($type, {GenericInterface}, [T1], function() { return []; }); return $type; }; {Type}.registerGenericInterface(exports, 'GenericInterface', $GenericInterface, 1); //////////////////////////////////////////////////////////////////////////////// // Interface var $Interface = function() { }; //////////////////////////////////////////////////////////////////////////////// // NormalClass var $NormalClass = function() { }; //////////////////////////////////////////////////////////////////////////////// // ResourceClass var $ResourceClass = { Field1: 'the value', Field2: 123, Field3: null }; {Type}.registerInterface(exports, 'Interface', $Interface, []); {Type}.registerClass(exports, 'NormalClass', $NormalClass); {Type}.registerType(exports, 'ResourceClass', $ResourceClass); ", new MockScriptSharpMetadataImporter { IsResources = t => t.FullName == "ResourceClass", GetModuleName = t => "my-module" }, new JsClass(CreateMockTypeDefinition("NormalClass"), JsClass.ClassTypeEnum.Class, null, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("GenericClass"), JsClass.ClassTypeEnum.Class, new[] { "T1" }, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("Interface"), JsClass.ClassTypeEnum.Interface, null, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("GenericInterface"), JsClass.ClassTypeEnum.Interface, new[] { "T1" }, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("ResourceClass"), JsClass.ClassTypeEnum.Class, null, null, new JsExpression[0]) { StaticInitStatements = { new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field1"), JsExpression.String("the value"))), new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field2"), JsExpression.Number(123))), new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field3"), JsExpression.Null)), } }); }
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 } var defaultConstructor = c.CSharpTypeDefinition.GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic); if (defaultConstructor != null) { JsExpression createInstance = CreateDefaultConstructorInvocation(defaultConstructor, typeRef); if (createInstance != null) { stmts.Add(new JsExpressionStatement( JsExpression.Assign( JsExpression.MemberAccess(typeRef, "createInstance"), JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(createInstance))))); } } 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)))))); } } }
public void InternalTypesAreNotExported() { var outerType = CreateMockTypeDefinition("Outer", Accessibility.Internal); var innerType = CreateMockTypeDefinition("Inner", Accessibility.Public, outerType); AssertCorrect( @"//////////////////////////////////////////////////////////////////////////////// // GenericClass var $GenericClass = function(T1) { var $type = function() { }; {Type}.registerGenericClassInstance($type, {GenericClass}, [T1], function() { return; }, function() { return []; }); return $type; }; {Type}.registerGenericClass(null, 'GenericClass', $GenericClass, 1); //////////////////////////////////////////////////////////////////////////////// // GenericInterface var $GenericInterface = function(T1) { var $type = function() { }; {Type}.registerGenericInterfaceInstance($type, {GenericInterface}, [T1], function() { return []; }); return $type; }; {Type}.registerGenericInterface(null, 'GenericInterface', $GenericInterface, 1); //////////////////////////////////////////////////////////////////////////////// // Interface var $Interface = function() { }; //////////////////////////////////////////////////////////////////////////////// // Outer var $Outer = function() { }; //////////////////////////////////////////////////////////////////////////////// // Inner var $Outer$Inner = function() { }; //////////////////////////////////////////////////////////////////////////////// // ResourceClass var $ResourceClass = { Field1: 'the value', Field2: 123, Field3: null }; {Type}.registerInterface(null, 'Interface', $Interface, []); {Type}.registerClass(null, 'Outer', $Outer); {Type}.registerClass(null, 'Outer$Inner', $Outer$Inner); ", new MockScriptSharpMetadataImporter { IsResources = t => t.FullName == "ResourceClass" }, new JsClass(outerType, JsClass.ClassTypeEnum.Class, null, null, new JsExpression[0]), new JsClass(innerType, JsClass.ClassTypeEnum.Class, null, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("GenericClass", Accessibility.Internal), JsClass.ClassTypeEnum.Class, new[] { "T1" }, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("Interface", Accessibility.Internal), JsClass.ClassTypeEnum.Interface, null, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("GenericInterface", Accessibility.Internal), JsClass.ClassTypeEnum.Interface, new[] { "T1" }, null, new JsExpression[0]), new JsClass(CreateMockTypeDefinition("ResourceClass", Accessibility.Internal), JsClass.ClassTypeEnum.Class, null, null, new JsExpression[0]) { StaticInitStatements = { new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field1"), JsExpression.String("the value"))), new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field2"), JsExpression.Number(123))), new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(new JsTypeReferenceExpression(Common.CreateMockType("SomeNamespace.InnerNamespace.MyClass")), "Field3"), JsExpression.Null)), } }); }
public IList <JsStatement> Rewrite(IEnumerable <JsType> types, ICompilation compilation) { var netSystemType = compilation.FindType(KnownTypeCode.Type).GetDefinition(); var systemType = new JsTypeReferenceExpression(netSystemType.ParentAssembly, _metadataImporter.GetTypeSemantics(netSystemType).Name); var result = new List <JsStatement>(); var orderedTypes = OrderByNamespace(types, t => t.Name).ToList(); string currentNs = ""; foreach (var t in orderedTypes) { try { var globalMethodsPrefix = _metadataImporter.GetGlobalMethodsPrefix(t.CSharpTypeDefinition); string ns = GetNamespace(t.Name); if (ns != currentNs && globalMethodsPrefix == null) { result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(systemType, RegisterNamespace), JsExpression.String(ns)))); currentNs = ns; } result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName)); var typeRef = new JsTypeReferenceExpression(compilation.MainAssembly, t.Name); if (t is JsClass) { var c = (JsClass)t; if (globalMethodsPrefix != null) { if (globalMethodsPrefix == "") { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.MemberAccess(JsExpression.Identifier("window"), m.Name), m.Definition)))); } else { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(globalMethodsPrefix + "." + m.Name), m.Definition)))); } } else if (_metadataImporter.IsResources(t.CSharpTypeDefinition)) { result.Add(GenerateResourcesClass(c)); } else { var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement); if (c.TypeArgumentNames.Count == 0) { result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, unnamedCtor))); AddClassMembers(c, typeRef, compilation, result); } else { var stmts = new List <JsStatement> { new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor) }; AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), compilation, stmts); stmts.AddRange(c.StaticInitStatements); stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName))); result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, JsExpression.FunctionDefinition(c.TypeArgumentNames, new JsBlockStatement(stmts))))); result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, c.ClassType == JsClass.ClassTypeEnum.Interface ? RegisterGenericInterface : RegisterGenericClass), JsExpression.String(c.Name), JsExpression.Number(c.TypeArgumentNames.Count)))); } } } else if (t is JsEnum) { var e = (JsEnum)t; bool flags = GetAttributePositionalArgs(t.CSharpTypeDefinition, FlagsAttribute, "System") != null; result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement)))); result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, Prototype), JsExpression.ObjectLiteral(e.Values.Select(v => new JsObjectLiteralProperty(v.Name, (_metadataImporter.IsNamedValues(t.CSharpTypeDefinition) ? JsExpression.String(v.Name) : JsExpression.Number(v.Value)))))))); result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterEnum), JsExpression.String(t.Name), JsExpression.Boolean(flags)))); } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } var typesToRegister = orderedTypes.OfType <JsClass>() .Where(c => c.TypeArgumentNames.Count == 0 && _metadataImporter.GetGlobalMethodsPrefix(c.CSharpTypeDefinition) == null && !_metadataImporter.IsResources(c.CSharpTypeDefinition)) .ToList(); result.AddRange(TopologicalSortTypesByInheritance(typesToRegister) .Select(c => { try { var typeRef = new JsTypeReferenceExpression(compilation.MainAssembly, c.Name); if (c.ClassType == JsClass.ClassTypeEnum.Interface) { return(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterInterface), JsExpression.String(c.Name), JsExpression.ArrayLiteral(c.ImplementedInterfaces))); } else { return(CreateRegisterClassCall(JsExpression.String(c.Name), c.BaseClass, c.ImplementedInterfaces, typeRef)); } } catch (Exception ex) { _errorReporter.Region = c.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName); return(JsExpression.Number(0)); } }) .Select(expr => new JsExpressionStatement(expr))); result.AddRange(orderedTypes.OfType <JsClass>().Where(c => c.TypeArgumentNames.Count == 0 && !_metadataImporter.IsResources(c.CSharpTypeDefinition)).SelectMany(t => t.StaticInitStatements)); return(result); }
private static JsExpression ConstructConstructorInfo(IMethod constructor, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType) { var properties = GetCommonMemberInfoProperties(constructor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); var sem = metadataImporter.GetConstructorSemantics(constructor); if (sem.Type == ConstructorScriptSemantics.ImplType.NotUsableFromScript) { errorReporter.Message(Messages._7200, constructor.FullName); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Constructor))); properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(constructor.Parameters.Select(p => instantiateType(p.Type))))); if (sem.Type == ConstructorScriptSemantics.ImplType.NamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod) { properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } if (sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod) { properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True)); } if ((sem.Type == ConstructorScriptSemantics.ImplType.UnnamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.NamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod) && sem.ExpandParams) { properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True)); } if (sem.Type == ConstructorScriptSemantics.ImplType.Json || sem.Type == ConstructorScriptSemantics.ImplType.InlineCode) { var usedNames = new HashSet <string>(); var parameters = new List <IVariable>(); var variables = new Dictionary <IVariable, VariableData>(); IList <ResolveResult> constructorParameters = null; IList <ResolveResult> initializerStatements = null; if (sem.Type == ConstructorScriptSemantics.ImplType.Json && constructor.DeclaringType.Kind == TypeKind.Anonymous) { initializerStatements = new List <ResolveResult>(); foreach (var p in constructor.DeclaringType.GetProperties()) { string paramName = MakeCamelCase(p.Name); string name = namer.GetVariableName(paramName, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.ReturnType, paramName, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); initializerStatements.Add(new OperatorResolveResult(p.ReturnType, ExpressionType.Assign, new MemberResolveResult(new InitializedObjectResolveResult(constructor.DeclaringType), p), new LocalResolveResult(variable))); } } else { constructorParameters = new List <ResolveResult>(); foreach (var p in constructor.Parameters) { string name = namer.GetVariableName(p.Name, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); constructorParameters.Add(new LocalResolveResult(variable)); } } var compileResult = CompileConstructorInvocation(constructor, initializerStatements, constructor.DeclaringTypeDefinition, constructor, constructorParameters, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, variables, usedNames); var definition = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), JsStatement.Block(compileResult.AdditionalStatements.Concat(new[] { JsStatement.Return(compileResult.Expression) }))); properties.Add(new JsObjectLiteralProperty("def", definition)); } return(JsExpression.ObjectLiteral(properties)); }
private JsExpression CreateInitEnumCall(JsEnum type, string ctorName) { var values = new List <JsObjectLiteralProperty>(); foreach (var v in type.CSharpTypeDefinition.Fields) { if (v.ConstantValue != null) { var sem = _metadataImporter.GetFieldSemantics(v); if (sem.Type == FieldScriptSemantics.ImplType.Field) { values.Add(new JsObjectLiteralProperty(sem.Name, JsExpression.Number(Convert.ToDouble(v.ConstantValue)))); } else if (sem.Type == FieldScriptSemantics.ImplType.Constant && sem.Name != null) { values.Add(new JsObjectLiteralProperty(sem.Name, sem.Value is string?JsExpression.String((string)sem.Value) : JsExpression.Number(Convert.ToDouble(sem.Value)))); } } else { _errorReporter.Region = v.Region; _errorReporter.InternalError("Enum field " + v.FullName + " is not constant."); } } var args = new List <JsExpression> { JsExpression.Identifier(ctorName), _linker.CurrentAssemblyExpression, JsExpression.ObjectLiteral(values) }; if (MetadataUtils.IsNamedValues(type.CSharpTypeDefinition, _attributeStore)) { args.Add(JsExpression.True); } return(JsExpression.Invocation(JsExpression.Member(_systemScript, InitEnum), args)); }
public MockRuntimeLibrary() { GetTypeOf = (t, c) => GetScriptType(t, TypeContext.TypeOf, c.ResolveTypeParameter); InstantiateType = (t, c) => GetScriptType(t, TypeContext.UseStaticMember, c.ResolveTypeParameter); InstantiateTypeForUseAsTypeArgumentInInlineCode = (t, c) => GetScriptType(t, TypeContext.GenericArgument, c.ResolveTypeParameter); TypeIs = (e, s, t, c) => JsExpression.Invocation(JsExpression.Identifier("$TypeIs"), e, GetScriptType(t, TypeContext.CastTarget, c.ResolveTypeParameter)); TryDowncast = (e, s, d, c) => JsExpression.Invocation(JsExpression.Identifier("$TryCast"), e, GetScriptType(d, TypeContext.CastTarget, c.ResolveTypeParameter)); Downcast = (e, s, d, c) => JsExpression.Invocation(JsExpression.Identifier("$Cast"), e, GetScriptType(d, TypeContext.CastTarget, c.ResolveTypeParameter)); Upcast = (e, s, d, c) => JsExpression.Invocation(JsExpression.Identifier("$Upcast"), e, GetScriptType(d, TypeContext.CastTarget, c.ResolveTypeParameter)); ReferenceEquals = (a, b, c) => JsExpression.Invocation(JsExpression.Identifier("$ReferenceEquals"), a, b); ReferenceNotEquals = (a, b, c) => JsExpression.Invocation(JsExpression.Identifier("$ReferenceNotEquals"), a, b); InstantiateGenericMethod = (m, a, c) => JsExpression.Invocation(JsExpression.Identifier("$InstantiateGenericMethod"), new[] { m }.Concat(a.Select(x => GetScriptType(x, TypeContext.GenericArgument, c.ResolveTypeParameter)))); MakeException = (e, c) => JsExpression.Invocation(JsExpression.Identifier("$MakeException"), e); IntegerDivision = (n, d, c) => JsExpression.Invocation(JsExpression.Identifier("$IntDiv"), n, d); FloatToInt = (e, c) => JsExpression.Invocation(JsExpression.Identifier("$Truncate"), e); Coalesce = (a, b, c) => JsExpression.Invocation(JsExpression.Identifier("$Coalesce"), a, b); Lift = (e, t, c) => JsExpression.Invocation(JsExpression.Identifier("$Lift"), e, JsExpression.Identifier(t.ToString())); FromNullable = (e, c) => JsExpression.Invocation(JsExpression.Identifier("$FromNullable"), e); LiftedBooleanAnd = (a, b, c) => JsExpression.Invocation(JsExpression.Identifier("$LiftedBooleanAnd"), a, b); LiftedBooleanOr = (a, b, c) => JsExpression.Invocation(JsExpression.Identifier("$LiftedBooleanOr"), a, b); LiftedBooleanXor = (a, b, c) => JsExpression.Invocation(JsExpression.Identifier("$LiftedBooleanXor"), a, b); Bind = (f, t, c) => JsExpression.Invocation(JsExpression.Identifier("$Bind"), f, t); BindFirstParameterToThis = (f, c) => JsExpression.Invocation(JsExpression.Identifier("$BindFirstParameterToThis"), f); Default = (t, c) => t.Kind == TypeKind.Dynamic ? (JsExpression)JsExpression.Identifier("$DefaultDynamic") : JsExpression.Invocation(JsExpression.Identifier("$Default"), GetScriptType(t, TypeContext.GetDefaultValue, c.ResolveTypeParameter)); CreateArray = (t, dim, c) => JsExpression.Invocation(JsExpression.Identifier("$CreateArray"), new[] { GetScriptType(t, TypeContext.GetDefaultValue, c.ResolveTypeParameter) }.Concat(dim)); CloneDelegate = (e, s, t, c) => JsExpression.Invocation(JsExpression.Identifier("$CloneDelegate"), e); CallBase = (m, a, c) => JsExpression.Invocation(JsExpression.Identifier("$CallBase"), new[] { GetScriptType(m.DeclaringType, TypeContext.BindBaseCall, c.ResolveTypeParameter), JsExpression.String("$" + m.Name), JsExpression.ArrayLiteral(m is SpecializedMethod ? ((SpecializedMethod)m).TypeArguments.Select(x => GetScriptType(x, TypeContext.GenericArgument, c.ResolveTypeParameter)) : new JsExpression[0]), JsExpression.ArrayLiteral(a) }); BindBaseCall = (m, a, c) => JsExpression.Invocation(JsExpression.Identifier("$BindBaseCall"), new[] { GetScriptType(m.DeclaringType, TypeContext.BindBaseCall, c.ResolveTypeParameter), JsExpression.String("$" + m.Name), JsExpression.ArrayLiteral(m is SpecializedMethod ? ((SpecializedMethod)m).TypeArguments.Select(x => GetScriptType(x, TypeContext.GenericArgument, c.ResolveTypeParameter)) : new JsExpression[0]), a }); MakeEnumerator = (yt, mn, gc, d, c) => JsExpression.Invocation(JsExpression.Identifier("$MakeEnumerator"), new[] { GetScriptType(yt, TypeContext.GenericArgument, c.ResolveTypeParameter), mn, gc, d ?? JsExpression.Null }); MakeEnumerable = (yt, ge, c) => JsExpression.Invocation(JsExpression.Identifier("$MakeEnumerable"), new[] { GetScriptType(yt, TypeContext.GenericArgument, c.ResolveTypeParameter), ge }); GetMultiDimensionalArrayValue = (a, i, c) => JsExpression.Invocation(JsExpression.Identifier("$MultidimArrayGet"), new[] { a }.Concat(i)); SetMultiDimensionalArrayValue = (a, i, v, c) => JsExpression.Invocation(JsExpression.Identifier("$MultidimArraySet"), new[] { a }.Concat(i).Concat(new[] { v })); CreateTaskCompletionSource = (t, c) => JsExpression.Invocation(JsExpression.Identifier("$CreateTaskCompletionSource"), t != null ? GetScriptType(t, TypeContext.GenericArgument, c.ResolveTypeParameter) : JsExpression.String("non-generic")); SetAsyncResult = (t, v, c) => JsExpression.Invocation(JsExpression.Identifier("$SetAsyncResult"), t, v ?? JsExpression.String("<<null>>")); SetAsyncException = (t, e, c) => JsExpression.Invocation(JsExpression.Identifier("$SetAsyncException"), t, e); GetTaskFromTaskCompletionSource = (t, c) => JsExpression.Invocation(JsExpression.Identifier("$GetTask"), t); ApplyConstructor = (c, a, x) => JsExpression.Invocation(JsExpression.Identifier("$ApplyConstructor"), c, a); ShallowCopy = (s, t, c) => JsExpression.Invocation(JsExpression.Identifier("$ShallowCopy"), s, t); GetMember = (m, c) => JsExpression.Invocation(JsExpression.Identifier("$GetMember"), GetScriptType(m.DeclaringType, TypeContext.TypeOf, c.ResolveTypeParameter), JsExpression.String(m.Name)); GetExpressionForLocal = (n, a, t, c) => JsExpression.Invocation(JsExpression.Identifier("$Local"), JsExpression.String(n), GetScriptType(t, TypeContext.TypeOf, c.ResolveTypeParameter), a); CloneValueType = (v, t, c) => JsExpression.Invocation(JsExpression.Identifier("$Clone"), v, GetScriptType(t, TypeContext.TypeOf, c.ResolveTypeParameter)); InitializeField = (t, n, m, v, c) => JsExpression.Invocation(JsExpression.Identifier("$Init"), t, JsExpression.String(n), v); }
public static IList <string> ValidateLiteralCode(IMethod method, string literalCode, Func <ITypeReference, IType> resolveType) { var errors = new List <string>(); CompileInlineCodeMethodInvocation(method, literalCode, method.IsStatic ? null : JsExpression.Null, method.Parameters.Select(p => p.IsParams ? (JsExpression)JsExpression.ArrayLiteral() : JsExpression.String("X")).ToList(), resolveType, (t, c) => JsExpression.Null, true, errors.Add); return(errors); }