public void VisitNode(JSIndexerExpression idx) { Visit(idx.Target); Output.OpenBracket(); Visit(idx.Index); Output.CloseBracket(); }
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 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 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 ForwardDeclareType(DecompilerContext context, JavascriptFormatter output, TypeDefinition typedef) { var typeInfo = TypeInfoProvider.GetTypeInformation(typedef); if ((typeInfo == null) || typeInfo.IsIgnored || typeInfo.IsProxy) return; if (DeclaredTypes.Contains(typedef.FullName)) { Debug.WriteLine("Cycle in type references detected: {0}", typedef); return; } context.CurrentType = typedef; output.DeclareNamespace(typedef.Namespace); DeclaredTypes.Add(typedef.FullName); if (typedef.IsInterface) { TranslateInterface(context, output, typedef); return; } else if (typedef.IsEnum) { TranslateEnum(context, output, typedef); return; } else if (typeInfo.IsDelegate) { TranslateDelegate(context, output, typedef, typeInfo); return; } var declaringType = typedef.DeclaringType; if (declaringType != null) { if (!DeclaredTypes.Contains(declaringType.FullName)) ForwardDeclareType(context, output, declaringType); } var baseClass = typedef.Module.TypeSystem.Object; if (typedef.BaseType != null) { baseClass = typedef.BaseType; var resolved = baseClass.Resolve(); if ( (resolved != null) && !DeclaredTypes.Contains(resolved.FullName) && (resolved.Module.Assembly == typedef.Module.Assembly) ) { ForwardDeclareType(context, output, resolved); } } bool isStatic = typedef.IsAbstract && typedef.IsSealed; if (isStatic) { output.Identifier("JSIL.MakeStaticClass", null); output.LPar(); output.Value(Util.EscapeIdentifier(typedef.FullName, EscapingMode.String)); output.Comma(); output.Value(typedef.IsPublic); if (typedef.HasGenericParameters) { output.Comma(); output.OpenBracket(); output.CommaSeparatedList( (from p in typedef.GenericParameters select p.Name), ListValueType.Primitive ); output.CloseBracket(); } output.RPar(); output.Semicolon(); } else { if (typedef.IsValueType) output.Identifier("JSIL.MakeStruct", null); else output.Identifier("JSIL.MakeClass", null); output.LPar(); if (!typedef.IsValueType) { output.TypeReference(baseClass); output.Comma(); } output.Value(Util.EscapeIdentifier(typedef.FullName, EscapingMode.String)); output.Comma(); output.Value(typedef.IsPublic); if (typedef.HasGenericParameters) { output.Comma(); output.OpenBracket(); output.CommaSeparatedList( (from p in typedef.GenericParameters select p.Name), ListValueType.Primitive ); output.CloseBracket(); } output.RPar(); output.Semicolon(); } foreach (var nestedTypeDef in typedef.NestedTypes) { if (!DeclaredTypes.Contains(nestedTypeDef.FullName)) ForwardDeclareType(context, output, nestedTypeDef); } 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); }
public void EmitInterfaceDefinition( DecompilerContext context, IAstEmitter astEmitter, TypeDefinition iface ) { Formatter.Identifier("JSIL.MakeInterface", EscapingMode.None); Formatter.LPar(); Formatter.NewLine(); Formatter.Value(Util.DemangleCecilTypeName(iface.FullName)); Formatter.Comma(); Formatter.Value(iface.IsPublic); Formatter.Comma(); Formatter.OpenBracket(); WriteGenericParameterNames(iface.GenericParameters); Formatter.CloseBracket(); Formatter.Comma(); Formatter.OpenFunction(null, (f) => f.Identifier("$") ); var refContext = new TypeReferenceContext { EnclosingType = iface, DefiningType = iface }; bool isFirst = true; foreach (var methodGroup in iface.Methods.GroupBy(md => md.Name)) { foreach (var m in methodGroup) { if (Translator.ShouldSkipMember(m)) { continue; } var methodInfo = _TypeInfoProvider.GetMethod(m); if ((methodInfo == null) || methodInfo.IsIgnored) { continue; } Formatter.Identifier("$", EscapingMode.None); Formatter.Dot(); Formatter.Identifier("Method", EscapingMode.None); Formatter.LPar(); Formatter.WriteRaw("{}"); Formatter.Comma(); Formatter.Value(Util.EscapeIdentifier(m.Name, EscapingMode.String)); Formatter.Comma(); Formatter.MethodSignature(m, methodInfo.Signature, refContext); Formatter.RPar(); Formatter.Semicolon(true); } } foreach (var p in iface.Properties) { var propertyInfo = _TypeInfoProvider.GetProperty(p); if ((propertyInfo != null) && propertyInfo.IsIgnored) { continue; } Formatter.Identifier("$", EscapingMode.None); Formatter.Dot(); Formatter.Identifier("Property", EscapingMode.None); Formatter.LPar(); Formatter.WriteRaw("{}"); Formatter.Comma(); Formatter.Value(Util.EscapeIdentifier(p.Name, EscapingMode.String)); Formatter.RPar(); Formatter.Semicolon(true); } Formatter.CloseBrace(false); Formatter.Comma(); refContext = new TypeReferenceContext { EnclosingType = iface.DeclaringType, DefiningType = iface }; Formatter.OpenBracket(); foreach (var i in iface.Interfaces) { if (!isFirst) { Formatter.Comma(); } Formatter.TypeReference(i, refContext); isFirst = false; } Formatter.CloseBracket(); Formatter.RPar(); EmitCustomAttributes(context, iface, iface, astEmitter); Formatter.Semicolon(); Formatter.NewLine(); }