protected void TranslateMethodGroup(DecompilerContext context, JavascriptFormatter output, MethodGroupInfo methodGroup) { var methods = (from m in methodGroup.Methods where !m.IsIgnored select m).ToArray(); if (methods.Length < 1) return; foreach (var method in methods) { foreach (var p in method.Member.Parameters) { var resolved = p.ParameterType.Resolve(); if ((resolved != null) && !DeclaredTypes.Contains(resolved.FullName) && (resolved.Module.Assembly == methodGroup.DeclaringType.Definition.Module.Assembly) ) { ForwardDeclareType(context, output, resolved); } } } output.Identifier( (methods.First().IsGeneric) ? "JSIL.OverloadedGenericMethod" : "JSIL.OverloadedMethod", null ); output.LPar(); output.Identifier(methodGroup.DeclaringType.Definition); if (!methodGroup.IsStatic) { output.Dot(); output.Keyword("prototype"); } output.Comma(); output.Value(Util.EscapeIdentifier(methodGroup.Name)); output.Comma(); output.OpenBracket(true); bool isFirst = true; foreach (var method in methods) { if (!isFirst) { output.Comma(); output.NewLine(); } output.OpenBracket(); output.Value(Util.EscapeIdentifier(method.GetName(true))); output.Comma(); output.OpenBracket(); output.CommaSeparatedList( from p in method.Member.Parameters select p.ParameterType, ListValueType.TypeIdentifier ); output.CloseBracket(); output.CloseBracket(); isFirst = false; } output.CloseBracket(true, () => { output.RPar(); output.Semicolon(); }); }
protected void TranslateTypeDefinition(DecompilerContext context, JavascriptFormatter output, TypeDefinition typedef, List<Action> initializer, bool stubbed) { var typeInfo = TypeInfoProvider.GetTypeInformation(typedef); if (!ShouldTranslateMethods(typedef)) return; context.CurrentType = typedef; var externalMemberNames = new HashSet<string>(); var staticExternalMemberNames = new HashSet<string>(); foreach (var method in typedef.Methods) { // We translate the static constructor explicitly later, and inject field initialization if (method.Name == ".cctor") continue; TranslateMethod( context, output, method, method, stubbed, externalMemberNames, staticExternalMemberNames ); } Action initializeOverloadsAndProperties = () => { foreach (var methodGroup in typeInfo.MethodGroups) TranslateMethodGroup(context, output, methodGroup); foreach (var property in typedef.Properties) TranslateProperty(context, output, property); }; if (!stubbed) initializeOverloadsAndProperties(); Func<TypeReference, bool> isInterfaceIgnored = (i) => { var interfaceInfo = TypeInfoProvider.GetTypeInformation(i); if (interfaceInfo != null) return interfaceInfo.IsIgnored; else return true; }; var interfaces = (from i in typeInfo.Interfaces where !i.IsIgnored select i).ToArray(); if (interfaces.Length > 0) { initializer.Add(() => { output.Identifier("JSIL.ImplementInterfaces", null); output.LPar(); output.Identifier(typedef); output.Comma(); output.OpenBracket(true); output.CommaSeparatedList(interfaces, ListValueType.TypeReference); output.CloseBracket(true, () => { output.RPar(); output.Semicolon(); }); }); } Func<FieldDefinition, bool> isFieldIgnored = (f) => { IMemberInfo memberInfo; if (typeInfo.Members.TryGetValue(MemberIdentifier.New(f), out memberInfo)) return memberInfo.IsIgnored; else return true; }; var structFields = (from field in typedef.Fields where !isFieldIgnored(field) && !field.HasConstant && EmulateStructAssignment.IsStruct(field.FieldType) && !field.IsStatic select field).ToArray(); if (structFields.Length > 0) { initializer.Add(() => { output.Identifier(typedef); output.Dot(); output.Identifier("prototype"); output.Dot(); output.Identifier("__StructFields__"); output.Token(" = "); output.OpenBracket(true); bool isFirst = true; foreach (var sf in structFields) { if (!isFirst) { output.Comma(); output.NewLine(); } output.OpenBracket(); output.Value(sf.Name); output.Comma(); output.Identifier(sf.FieldType); output.CloseBracket(); isFirst = false; } output.CloseBracket(true, output.Semicolon); }); } TranslateTypeStaticConstructor(context, output, typedef, typeInfo.StaticConstructor, stubbed); if (externalMemberNames.Count + staticExternalMemberNames.Count > 0) { initializer.Add(() => { if (externalMemberNames.Count > 0) { output.Identifier("JSIL.ExternalMembers", null); output.LPar(); output.Identifier(typedef); output.Dot(); output.Keyword("prototype"); output.Comma(); output.NewLine(); output.CommaSeparatedList(externalMemberNames, ListValueType.Primitive); output.NewLine(); output.RPar(); output.Semicolon(); } if (staticExternalMemberNames.Count > 0) { output.Identifier("JSIL.ExternalMembers", null); output.LPar(); output.Identifier(typedef); output.Comma(); output.NewLine(); output.CommaSeparatedList(staticExternalMemberNames, ListValueType.Primitive); output.NewLine(); output.RPar(); output.Semicolon(); } }); } if (stubbed && (typeInfo.MethodGroups.Count + typedef.Properties.Count) > 0 ) { initializer.Add(initializeOverloadsAndProperties); } output.NewLine(); foreach (var nestedTypedef in typedef.NestedTypes) TranslateTypeDefinition(context, output, nestedTypedef, initializer, stubbed); }
protected void TranslateMethod( DecompilerContext context, JavascriptFormatter output, MethodReference methodRef, MethodDefinition method, bool stubbed, HashSet<string> externalMemberNames, HashSet<string> staticExternalMemberNames, Action<JSFunctionExpression> bodyTransformer = null ) { var methodInfo = TypeInfoProvider.GetMemberInformation<Internal.MethodInfo>(method); if (methodInfo == null) return; bool isReplaced = methodInfo.Metadata.HasAttribute("JSIL.Meta.JSReplacement"); bool methodIsProxied = (methodInfo.IsFromProxy && methodInfo.Member.HasBody) && !methodInfo.IsExternal && !isReplaced; if (methodInfo.IsExternal || (stubbed && !methodIsProxied)) { if (isReplaced) return; if (externalMemberNames == null) throw new ArgumentNullException("externalMemberNames"); if (staticExternalMemberNames == null) throw new ArgumentNullException("staticExternalMemberNames"); var isProperty = methodInfo.DeclaringProperty != null; if (!isProperty || !methodInfo.Member.IsCompilerGenerated()) { (method.IsStatic ? staticExternalMemberNames : externalMemberNames) .Add(Util.EscapeIdentifier(methodInfo.GetName(true))); return; } } if (methodInfo.IsIgnored) return; if (!method.HasBody) return; if (methodIsProxied) { output.Comment("Implementation from {0}", methodInfo.Member.DeclaringType.FullName); output.NewLine(); } output.Identifier(method.DeclaringType); if (!method.IsStatic) { output.Dot(); output.Keyword("prototype"); } output.Dot(); output.Identifier(methodInfo.GetName(true)); output.Token(" = "); if (method.HasGenericParameters) { output.Identifier("JSIL.GenericMethod", null); output.LPar(); output.NewLine(); output.OpenBracket(); output.CommaSeparatedList((from p in method.GenericParameters select p.Name), ListValueType.Primitive); output.CloseBracket(); output.Comma(); output.NewLine(); } JSFunctionExpression function; function = FunctionCache.GetExpression(new QualifiedMemberIdentifier( methodInfo.DeclaringType.Identifier, methodInfo.Identifier )); if (bodyTransformer != null) bodyTransformer(function); if (function != null) { AstEmitter.Visit(function); } else { output.Identifier("JSIL.UntranslatableFunction", null); output.LPar(); output.Value(method.FullName); output.RPar(); } if (method.HasGenericParameters) { output.NewLine(); output.RPar(); } output.Semicolon(); }
protected void TranslateProperty(DecompilerContext context, JavascriptFormatter output, PropertyDefinition property) { var propertyInfo = TypeInfoProvider.GetMemberInformation<Internal.PropertyInfo>(property); if ((propertyInfo == null) || propertyInfo.IsIgnored) return; var isStatic = (property.SetMethod ?? property.GetMethod).IsStatic; if (property.DeclaringType.HasGenericParameters && isStatic) output.Identifier("JSIL.MakeGenericProperty", null); else output.Identifier("JSIL.MakeProperty", null); output.LPar(); output.Identifier(property.DeclaringType); if (!isStatic) { output.Dot(); output.Keyword("prototype"); } output.Comma(); output.Value(Util.EscapeIdentifier(propertyInfo.Name)); output.Comma(); output.NewLine(); if (property.GetMethod != null) { output.Identifier(property.DeclaringType); if (!isStatic) { output.Dot(); output.Keyword("prototype"); } output.Dot(); output.Identifier(property.GetMethod, false); } else { output.Keyword("null"); } output.Comma(); if (property.SetMethod != null) { output.Identifier(property.DeclaringType); if (!isStatic) { output.Dot(); output.Keyword("prototype"); } output.Dot(); output.Identifier(property.SetMethod, false); } else { output.Keyword("null"); } output.RPar(); output.Semicolon(); }