public static JsExpression ResolveTypeParameter(ITypeParameter tp, ITypeDefinition currentType, IMethod currentMethod, IMetadataImporter metadataImporter, IErrorReporter errorReporter, INamer namer) { bool unusable = false; switch (tp.OwnerType) { case EntityType.TypeDefinition: unusable = metadataImporter.GetTypeSemantics(currentType).IgnoreGenericArguments; break; case EntityType.Method: { var sem = metadataImporter.GetMethodSemantics(currentMethod); unusable = sem.Type != MethodScriptSemantics.ImplType.InlineCode && metadataImporter.GetMethodSemantics(currentMethod).IgnoreGenericArguments; break; } default: errorReporter.InternalError("Invalid owner " + tp.OwnerType + " for type parameter " + tp); return(JsExpression.Null); } if (unusable) { errorReporter.Message(Messages._7536, tp.Name, tp.OwnerType == EntityType.TypeDefinition ? "type" : "method", tp.OwnerType == EntityType.TypeDefinition ? currentType.FullName : currentMethod.FullName); return(JsExpression.Null); } return(JsExpression.Identifier(namer.GetTypeParameterName(tp))); }
public JsExpression ResolveTypeParameter(ITypeParameter tp) { if (_isGenericSpecialization && tp.OwnerType == EntityType.TypeDefinition) { return(JsExpression.Identifier(_namer.GetTypeParameterName(tp))); } else { return(_systemObject); } }
public JsExpression ResolveTypeParameter(ITypeParameter tp) { if (_metadataImporter.GetTypeSemantics(_currentType).IgnoreGenericArguments) { _errorReporter.Message(Saltarelle.Compiler.Messages._7536, tp.Name, "type", _currentType.FullName); return(JsExpression.Null); } else { return(JsExpression.Identifier(_namer.GetTypeParameterName(tp))); } }
private void MaybeCompileAndAddMethodToType(JsClass jsClass, EntityDeclaration node, BlockStatement body, IMethod method, MethodScriptSemantics options) { if (options.GeneratedMethodName != null) { 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.GeneratedMethodName, typeParamNames, null); } else { var compiled = CompileMethod(node, body, method, options); jsMethod = new JsMethod(method, options.GeneratedMethodName, typeParamNames, compiled); } AddCompiledMethodToType(jsClass, method, options, jsMethod); } }
private void AddClassMembers(JsClass c, JsExpression typeRef, List <JsStatement> stmts) { if (c.InstanceMethods.Count > 0) { stmts.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(c.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.Member(typeRef, m.Name), m.Definition)))); stmts.Add(new JsExpressionStatement(c.NamedConstructors.Reverse().Aggregate((JsExpression)JsExpression.Member(typeRef, Prototype), (right, ctor) => JsExpression.Assign(JsExpression.Member(JsExpression.Member(typeRef, ctor.Name), Prototype), right)))); // This generates a statement like {C}.ctor1.prototype = {C}.ctor2.prototype = {C}.prototoype } var defaultConstructor = Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition).GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic); if (defaultConstructor != null) { var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor); if (sem.Type != ConstructorScriptSemantics.ImplType.UnnamedConstructor && sem.Type != ConstructorScriptSemantics.ImplType.NotUsableFromScript) { var createInstance = MetadataUtils.CompileConstructorInvocation(defaultConstructor, null, c.CSharpTypeDefinition, null, EmptyList <ResolveResult> .Instance, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter, null, null); stmts.Add(new JsExpressionStatement( JsExpression.Assign( JsExpression.Member(typeRef, "createInstance"), JsExpression.FunctionDefinition(new string[0], new JsBlockStatement(createInstance.AdditionalStatements.Concat(new[] { new JsReturnStatement(createInstance.Expression) })))))); } } stmts.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, m.Name), RewriteMethod(m))))); if (MetadataUtils.IsSerializable(c.CSharpTypeDefinition)) { string typeCheckCode = MetadataUtils.GetSerializableTypeCheckCode(c.CSharpTypeDefinition); if (!string.IsNullOrEmpty(typeCheckCode)) { var oldReg = _errorReporter.Region; _errorReporter.Region = c.CSharpTypeDefinition.Attributes.Single(a => a.AttributeType.FullName == typeof(SerializableAttribute).FullName).Region; var method = MetadataUtils.CreateTypeCheckMethod(Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition), _compilation); var errors = new List <string>(); var tokens = InlineCodeMethodCompiler.Tokenize(method, typeCheckCode, errors.Add); if (errors.Count == 0) { var context = new DefaultRuntimeContext(c.CSharpTypeDefinition, _metadataImporter, _errorReporter, _namer); var result = InlineCodeMethodCompiler.CompileInlineCodeMethodInvocation(method, tokens, JsExpression.Identifier("obj"), new JsExpression[0], n => { var type = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); if (type.Kind == TypeKind.Unknown) { errors.Add("Unknown type '" + n + "' specified in inline implementation"); return(JsExpression.Null); } return(_runtimeLibrary.InstantiateType(type, context)); }, t => _runtimeLibrary.InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), errors.Add); stmts.Add(new JsExpressionStatement( JsExpression.Assign( JsExpression.Member(typeRef, "isInstanceOfType"), JsExpression.FunctionDefinition(new[] { "obj" }, new JsReturnStatement(result))))); foreach (var e in errors) { _errorReporter.Message(Messages._7157, c.CSharpTypeDefinition.FullName, e); } } _errorReporter.Region = oldReg; } } if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var args = new List <JsExpression> { typeRef, new JsTypeReferenceExpression(c.CSharpTypeDefinition), JsExpression.ArrayLiteral(c.CSharpTypeDefinition.TypeParameters.Select(tp => JsExpression.Identifier(_namer.GetTypeParameterName(tp)))) }; if (c.CSharpTypeDefinition.Kind == TypeKind.Class) { args.Add(JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(GetBaseClass(c.CSharpTypeDefinition) ?? JsExpression.Null))); } args.Add(JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(JsExpression.ArrayLiteral(GetImplementedInterfaces(c.CSharpTypeDefinition))))); var metadata = GetMetadataDescriptor(c.CSharpTypeDefinition, true); if (metadata != null) { args.Add(metadata); } stmts.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Class ? RegisterGenericClassInstance : RegisterGenericInterfaceInstance), args))); } }
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(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(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 CreateCompilationContext(AstNode entity, IMethod method, ITypeDefinition type, string thisAlias) { _usedNames = method != null ? new HashSet <string>(method.DeclaringTypeDefinition.TypeParameters.Concat(method.TypeParameters).Select(p => _namer.GetTypeParameterName(p))) : new HashSet <string>(); if (entity != null) { var x = new VariableGatherer(_resolver, _namer, _errorReporter).GatherVariables(entity, method, _usedNames); variables = x.Item1; _usedNames = x.Item2; } nestedFunctionsRoot = entity != null ? new NestedFunctionGatherer(_resolver).GatherNestedFunctions(entity, variables) : new NestedFunctionData(null); var nestedFunctionsDict = new[] { nestedFunctionsRoot }.Concat(nestedFunctionsRoot.DirectlyOrIndirectlyNestedFunctions).Where(f => f.ResolveResult != null).ToDictionary(f => f.ResolveResult); _statementCompiler = new StatementCompiler(_metadataImporter, _namer, _errorReporter, _compilation, _resolver, variables, nestedFunctionsDict, _runtimeLibrary, thisAlias, _usedNames, null, method, type); }
public static JsExpression ResolveTypeParameter(ITypeParameter tp, ITypeDefinition currentType, IMethod currentMethod, IMetadataImporter metadataImporter, IErrorReporter errorReporter, INamer namer) { bool unusable = false; switch (tp.OwnerType) { case EntityType.TypeDefinition: unusable = metadataImporter.GetTypeSemantics(currentType).IgnoreGenericArguments; break; case EntityType.Method: { var sem = metadataImporter.GetMethodSemantics(currentMethod); unusable = sem.Type != MethodScriptSemantics.ImplType.InlineCode && metadataImporter.GetMethodSemantics(currentMethod).IgnoreGenericArguments; break; } default: errorReporter.InternalError("Invalid owner " + tp.OwnerType + " for type parameter " + tp); return JsExpression.Null; } if (unusable) { errorReporter.Message(Messages._7536, tp.Name, tp.OwnerType == EntityType.TypeDefinition ? "type" : "method", tp.OwnerType == EntityType.TypeDefinition ? currentType.FullName : currentMethod.FullName); return JsExpression.Null; } return JsExpression.Identifier(namer.GetTypeParameterName(tp)); }
private void AddClassMembers(JsClass c, string typevarName, List <JsStatement> stmts) { if (c.NamedConstructors.Count > 0) { stmts.AddRange(c.NamedConstructors.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), m.Definition))); } var defaultConstructor = Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition).GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic); bool hasCreateInstance = false; if (defaultConstructor != null) { var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor); if (sem.Type != ConstructorScriptSemantics.ImplType.UnnamedConstructor && sem.Type != ConstructorScriptSemantics.ImplType.NotUsableFromScript) { var createInstance = MetadataUtils.CompileConstructorInvocation(defaultConstructor, null, c.CSharpTypeDefinition, null, EmptyList <ResolveResult> .Instance, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter, null, null); stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance"), JsExpression.FunctionDefinition(new string[0], JsStatement.Block(createInstance.AdditionalStatements.Concat(new[] { JsStatement.Return(createInstance.Expression) }))))); hasCreateInstance = true; } } if (c.CSharpTypeDefinition.Kind == TypeKind.Struct) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "getDefaultValue"), hasCreateInstance ? JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance") : JsExpression.FunctionDefinition(EmptyList <string> .Instance, JsStatement.Return(JsExpression.New(JsExpression.Identifier(typevarName)))))); if (_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Type == TypeScriptSemantics.ImplType.MutableValueType) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "$clone"), GenerateStructCloneMethod(c.CSharpTypeDefinition, typevarName, hasCreateInstance))); } } stmts.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), RewriteMethod(m)))); if (MetadataUtils.IsSerializable(c.CSharpTypeDefinition, _attributeStore)) { string typeCheckCode = MetadataUtils.GetSerializableTypeCheckCode(c.CSharpTypeDefinition, _attributeStore); if (!string.IsNullOrEmpty(typeCheckCode)) { var oldReg = _errorReporter.Region; _errorReporter.Region = c.CSharpTypeDefinition.Attributes.Single(a => a.AttributeType.FullName == typeof(SerializableAttribute).FullName).Region; var method = MetadataUtils.CreateTypeCheckMethod(Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition), _compilation); var errors = new List <string>(); var tokens = InlineCodeMethodCompiler.Tokenize(method, typeCheckCode, errors.Add); if (errors.Count == 0) { var context = new DefaultRuntimeContext(c.CSharpTypeDefinition, _metadataImporter, _errorReporter, _namer); var result = InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, JsExpression.Identifier("obj"), new JsExpression[0], n => { var type = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); if (type.Kind == TypeKind.Unknown) { errors.Add("Unknown type '" + n + "' specified in inline implementation"); return(JsExpression.Null); } return(_runtimeLibrary.InstantiateType(type, context)); }, t => _runtimeLibrary.InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), errors.Add); stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "isInstanceOfType"), JsExpression.FunctionDefinition(new[] { "obj" }, JsStatement.Return(result)))); foreach (var e in errors) { _errorReporter.Message(Messages._7157, c.CSharpTypeDefinition.FullName, e); } } _errorReporter.Region = oldReg; } else { stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "isInstanceOfType"), JsExpression.FunctionDefinition(new string[0], JsStatement.Return(JsExpression.True)))); } } if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var args = new List <JsExpression> { JsExpression.Identifier(typevarName), new JsTypeReferenceExpression(c.CSharpTypeDefinition), JsExpression.ArrayLiteral(c.CSharpTypeDefinition.TypeParameters.Select(tp => JsExpression.Identifier(_namer.GetTypeParameterName(tp)))), CreateInstanceMembers(c, typevarName), }; if (c.CSharpTypeDefinition.Kind != TypeKind.Interface) { args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(GetBaseClass(c.CSharpTypeDefinition) ?? JsExpression.Null))); } args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(JsExpression.ArrayLiteral(GetImplementedInterfaces(c.CSharpTypeDefinition))))); stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterfaceInstance : RegisterGenericClassInstance), args)); if (c.CSharpTypeDefinition.Kind == TypeKind.Class && c.NamedConstructors.Count > 0) { stmts.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(typevarName))); } if (c.CSharpTypeDefinition.Kind == TypeKind.Struct) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "__class"), JsExpression.False)); } var metadata = GetMetadataDescriptor(c.CSharpTypeDefinition, true); if (metadata != null) { stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, SetMetadata), JsExpression.Identifier(typevarName), metadata)); } } }