public static JsExpression ConstructMemberInfo(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func<IType, JsExpression> instantiateType, bool includeDeclaringType) { MethodScriptSemantics semanticsIfAccessor = null; if (m is IMethod && ((IMethod)m).IsAccessor) { var owner = ((IMethod)m).AccessorOwner; if (owner is IProperty) { var sem = metadataImporter.GetPropertySemantics((IProperty)owner); if (sem.Type == PropertyScriptSemantics.ImplType.GetAndSetMethods) { if (ReferenceEquals(m, ((IProperty)owner).Getter)) semanticsIfAccessor = sem.GetMethod; else if (ReferenceEquals(m, ((IProperty)owner).Setter)) semanticsIfAccessor = sem.SetMethod; else throw new ArgumentException("Invalid member " + m); } } else if (owner is IEvent) { var sem = metadataImporter.GetEventSemantics((IEvent)owner); if (sem.Type == EventScriptSemantics.ImplType.AddAndRemoveMethods) { if (ReferenceEquals(m, ((IEvent)owner).AddAccessor)) semanticsIfAccessor = sem.AddMethod; else if (ReferenceEquals(m, ((IEvent)owner).RemoveAccessor)) semanticsIfAccessor = sem.RemoveMethod; else throw new ArgumentException("Invalid member " + m); } } else throw new ArgumentException("Invalid owner " + owner); } return ConstructMemberInfo(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, semanticsIfAccessor); }
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); }