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 TranslateEnum(DecompilerContext context, JavascriptFormatter output, TypeDefinition enm) { output.Identifier("JSIL.MakeEnum", null); output.LPar(); output.NewLine(); output.Value(Util.EscapeIdentifier(enm.FullName, EscapingMode.String)); output.Comma(); output.OpenBrace(); var typeInformation = TypeInfoProvider.GetTypeInformation(enm); if (typeInformation == null) throw new InvalidOperationException(); bool isFirst = true; foreach (var em in typeInformation.EnumMembers.Values) { if (!isFirst) { output.Comma(); output.NewLine(); } output.Identifier(em.Name); output.Token(": "); output.Value(em.Value); isFirst = false; } output.NewLine(); output.CloseBrace(false); output.Comma(); output.Value(typeInformation.IsFlagsEnum); output.NewLine(); output.RPar(); output.Semicolon(); output.NewLine(); }
protected void TranslateInterface(DecompilerContext context, JavascriptFormatter output, TypeDefinition iface) { output.Identifier("JSIL.MakeInterface", null); output.LPar(); output.NewLine(); output.Value(Util.EscapeIdentifier(iface.FullName, EscapingMode.String)); output.Comma(); output.OpenBracket(); output.CommaSeparatedList( (from p in iface.GenericParameters select p.Name), ListValueType.Primitive ); output.CloseBracket(); output.Comma(); output.OpenBrace(); bool isFirst = true; foreach (var m in iface.Methods) { var methodInfo = TypeInfoProvider.GetMethod(m); if ((methodInfo != null) && methodInfo.IsIgnored) continue; if (!isFirst) { output.Comma(); output.NewLine(); } output.Value(Util.EscapeIdentifier(m.Name)); output.Token(": "); output.Identifier("Function"); isFirst = false; } foreach (var p in iface.Properties) { var propertyInfo = TypeInfoProvider.GetProperty(p); if ((propertyInfo != null) && propertyInfo.IsIgnored) continue; if (!isFirst) { output.Comma(); output.NewLine(); } output.Value(Util.EscapeIdentifier(p.Name)); output.Token(": "); output.Identifier("Property"); isFirst = false; } output.NewLine(); output.CloseBrace(false); output.RPar(); output.Semicolon(); output.NewLine(); }
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); }