/// <summary> /// Checks whether specified method has parameters suitable for being event handler. /// </summary> private static bool CheckEventHandlerParameters(Method method) { if (method.Parameters.Count != 2) return false; Parameter sender = method.Parameters[0]; if (sender.Name != "sender") return false; if (sender.Type.Text != "object") return false; Parameter args = method.Parameters[1]; if (args.Name != "e") return false; if (!ExtractPureName(args.Type.Text, true).EndsWith("EventArgs")) return false; return true; }
/// <summary> /// Parses and returns a method. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Method ParseMethod( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; // Get the declared modifiers for the method. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, MethodModifiers); // Methods within interfaces always have the access of the parent interface. Interface parentInterface = parent as Interface; if (parentInterface != null) { accessModifier = parentInterface.AccessModifier; } unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); TypeToken returnType = null; if (!modifiers.ContainsKey(CsTokenType.Implicit) && !modifiers.ContainsKey(CsTokenType.Explicit)) { // Get the return type. returnType = this.GetTypeToken(elementReference, unsafeCode, true); this.tokens.Add(returnType); } // Get the name of the method. string methodName = null; Symbol symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType == SymbolType.Operator) { this.tokens.Add(this.GetToken(CsTokenType.Operator, SymbolType.Operator, elementReference)); // Advance up to the next symbol. this.AdvanceToNextCodeSymbol(elementReference); // The overloaded item will either be a type or a symbol. int endIndex = -1; CsToken operatorType = null; if (this.HasTypeSignature(1, unsafeCode, out endIndex)) { // The overloaded item is a type. operatorType = this.GetTypeToken(elementReference, unsafeCode, true); } else { // The overloaded item is a symbol. operatorType = this.ConvertOperatorOverloadSymbol(elementReference); } this.tokens.Add(operatorType); methodName = "operator " + operatorType.Text; } else { CsToken name = this.GetElementNameToken(elementReference, unsafeCode); methodName = name.Text; this.tokens.Add(name); } // Get the parameter list. IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis, modifiers.ContainsKey(CsTokenType.Static)); // Check whether there are any type constraint clauses. ICollection<TypeParameterConstraintClause> typeConstraints = null; symbol = this.GetNextSymbol(elementReference); if (symbol.Text == "where") { typeConstraints = this.ParseTypeConstraintClauses(elementReference, unsafeCode); } // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, methodName, ElementType.Method, accessModifier, modifiers); Method method = new Method(this.document, parent, xmlHeader, attributes, declaration, returnType, parameters, typeConstraints, unsafeCode, generated); elementReference.Target = method; // If the element is extern, abstract, or containing within an interface, it will not have a body. if (modifiers.ContainsKey(CsTokenType.Abstract) || modifiers.ContainsKey(CsTokenType.Extern) || parent.ElementType == ElementType.Interface) { // Get the closing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); } else { // Get the method body or bodied expression C# 6. this.ParseStatementContainer(method, true, unsafeCode); } return method; }
/// <summary> /// The save. /// </summary> /// <param name="methodDeclaration"> /// The method declaration. /// </param> private void Save(Method methodDeclaration) { this.CurrentParameters = methodDeclaration.Parameters; var methodName = methodDeclaration.Declaration.Name; var lastDot = methodName.LastIndexOf('.'); var nameWithoutNamespace = lastDot != -1 ? methodName.Substring(lastDot + 1, methodName.Length - lastDot - 1) : methodName; var methodInterfaceNamespace = lastDot != -1 ? methodName.Substring(0, lastDot) : string.Empty; var isGenericMethod = nameWithoutNamespace.Contains('<') && nameWithoutNamespace.Contains('>'); var isOperator = methodName.StartsWith("operator "); if (isOperator) { methodName = methodName.Substring("operator ".Length); switch (methodName) { case "==": methodName = RelationalExpression.Operator.EqualTo.ToString(); break; case "!=": methodName = RelationalExpression.Operator.NotEqualTo.ToString(); break; case ">": methodName = RelationalExpression.Operator.GreaterThan.ToString(); break; case ">=": methodName = RelationalExpression.Operator.GreaterThanOrEqualTo.ToString(); break; case "<": methodName = RelationalExpression.Operator.LessThan.ToString(); break; case "<=": methodName = RelationalExpression.Operator.LessThanOrEqualTo.ToString(); break; case "+": methodName = "Add"; break; case "-": methodName = "Remove"; break; default: break; } methodName = string.Concat("op_", methodName); nameWithoutNamespace = methodName; } // decide which mode 1/2 files to use; var restoreStateIsCppInHeader = this.IsCPPInHeader; if (!this.IsCPPInHeader) { this.IsCPPInHeader = isGenericMethod; } if (this.ClassContext.IsInterface) { this.IsCPPInHeader = true; } // 1 to destHeader this.Save(methodDeclaration.AccessModifier); this.headerWriter.Write(": "); var isImplicit = false; var isExplicit = false; // if generic, write template here if (isGenericMethod) { this.BuildDeclaretionTemplatePart(methodName); this.headerWriter.Write(this.BuildDeclaretionTemplatePart(methodName)); } methodDeclaration.SaveDeclatationsAfterModifiers(this.headerWriter); // ASD: HACK if (methodDeclaration.ReturnType != null) { // 1 to destHeader this.Save(methodDeclaration.ReturnType); if (!this.IsCPPInHeader) { // 2 to Source this.Save(methodDeclaration.ReturnType, this.cppWriter, SavingOptions.None); } } else { // check if it is implicit or explicit operators isImplicit = methodDeclaration.Declaration.ContainsModifier(CsTokenType.Implicit); isExplicit = methodDeclaration.Declaration.ContainsModifier(CsTokenType.Explicit); if (isImplicit || isExplicit) { // var returnType = new ResolvedTypeReference(typeConvertTypeName, this); // this.Save(returnType, this.destHeader, false); if (!this.IsCPPInHeader) { // 2 to Source // this.Save(returnType, this.destCPP, false); } } } var cppName = nameWithoutNamespace; cppName = isGenericMethod ? cppName.Split('<')[0] : cppName; // add namespace of interface if any if (!string.IsNullOrEmpty(methodInterfaceNamespace)) { // var typeResolverReference = new ResolvedTypeReference(methodInterfaceNamespace, this); // cppName = String.Concat(typeResolverReference.CNameFullyQualifiedName, "::", cppName); } if (isImplicit) { cppName = "op_Implicit"; } else if (isExplicit) { cppName = "op_Explicit"; } // 1 to destHeader this.headerWriter.Write(' '); this.headerWriter.Write(cppName); // 2 to Source if (!this.IsCPPInHeader) { this.cppWriter.Write(' '); this.cppWriter.Write(this.currentClassNamespace); this.cppWriter.Write("::"); this.cppWriter.Write(cppName); } this.SaveParametersAndBody(methodDeclaration); if (!this.IsCPPInHeader) { this.cppWriter.WriteLine(); } this.CurrentParameters = null; this.IsCPPInHeader = restoreStateIsCppInHeader; }