private MethodSymbol BuildMethod(MethodDeclarationNode methodNode, TypeSymbol typeSymbol) { MethodSymbol method = null; if (methodNode.NodeType == ParseNodeType.ConstructorDeclaration) { method = new ConstructorSymbol(typeSymbol, (methodNode.Modifiers & Modifiers.Static) != 0); } else { TypeSymbol returnType = typeSymbol.SymbolSet.ResolveType(methodNode.Type, _symbolTable, typeSymbol); Debug.Assert(returnType != null); if (returnType != null) { method = new MethodSymbol(methodNode.Name, typeSymbol, returnType); BuildMemberDetails(method, typeSymbol, methodNode, methodNode.Attributes); ICollection<string> conditions = null; foreach (AttributeNode attrNode in methodNode.Attributes) { if (attrNode.TypeName.Equals("Conditional", StringComparison.Ordinal)) { if (conditions == null) { conditions = new List<string>(); } Debug.Assert(attrNode.Arguments[0] is LiteralNode); Debug.Assert(((LiteralNode)attrNode.Arguments[0]).Value is string); conditions.Add((string)((LiteralNode)attrNode.Arguments[0]).Value); } } if (conditions != null) { method.SetConditions(conditions); } } } if (method != null) { if ((methodNode.Modifiers & Modifiers.Abstract) != 0) { method.SetImplementationState(SymbolImplementationFlags.Abstract); } else if ((methodNode.Modifiers & Modifiers.Override) != 0) { method.SetImplementationState(SymbolImplementationFlags.Override); } if ((methodNode.Parameters != null) && (methodNode.Parameters.Count != 0)) { foreach (ParameterNode parameterNode in methodNode.Parameters) { ParameterSymbol paramSymbol = BuildParameter(parameterNode, method); if (paramSymbol != null) { paramSymbol.SetParseContext(parameterNode); method.AddParameter(paramSymbol); } } } if ((method.Visibility & MemberVisibility.Static) != 0) { string scriptAlias = GetAttributeValue(methodNode.Attributes, "ScriptAlias"); if (scriptAlias != null) { method.SetAlias(scriptAlias); } } } return method; }
private void ImportMethods(TypeSymbol typeSymbol) { // NOTE: We do not import parameters for imported members. // Parameters are used in the script model generation phase to populate // symbol tables, which is not done for imported methods. TypeDefinition type = (TypeDefinition)typeSymbol.MetadataReference; foreach (MethodDefinition method in type.Methods) { if (method.IsSpecialName) { continue; } if (method.IsPrivate || method.IsAssembly || method.IsFamilyAndAssembly) { continue; } string methodName = method.Name; if (typeSymbol.GetMember(methodName) != null) { // Ignore if its an overload since we don't care about parameters // for imported methods, overloaded ctors don't matter. // We just care about return values pretty much, and existence of the // method. continue; } TypeSymbol returnType = ResolveType(method.MethodReturnType.ReturnType); if (returnType == null) { continue; } MethodSymbol methodSymbol = new MethodSymbol(methodName, typeSymbol, returnType); ImportMemberDetails(methodSymbol, method, method); if (method.HasGenericParameters) { List<GenericParameterSymbol> genericArguments = new List<GenericParameterSymbol>(); foreach (GenericParameter genericParameter in method.GenericParameters) { GenericParameterSymbol arg = new GenericParameterSymbol(genericParameter.Position, genericParameter.Name, /* typeArgument */ false, _symbols.GlobalNamespace); genericArguments.Add(arg); } methodSymbol.AddGenericArguments(genericArguments); } if (method.IsAbstract) { // NOTE: We're ignoring the override scenario - it doesn't matter in terms // of the compilation and code generation methodSymbol.SetImplementationState(SymbolImplementationFlags.Abstract); } if (MetadataHelpers.ShouldSkipFromScript(method)) { methodSymbol.SetSkipGeneration(); } if ((methodSymbol.Visibility & MemberVisibility.Static) != 0) { string alias = MetadataHelpers.GetScriptAlias(method); if (String.IsNullOrEmpty(alias) == false) { methodSymbol.SetAlias(alias); } } ICollection<string> conditions; if (MetadataHelpers.ShouldTreatAsConditionalMethod(method, out conditions)) { methodSymbol.SetConditions(conditions); } typeSymbol.AddMember(methodSymbol); } }