<commit_before>/* valacreationmethod.vala
 *
 * Copyright (C) 2007-2009  <NAME>
 * Copyright (C) 2007-2008  <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 *	<NAME> <<EMAIL>>
 * 	<NAME> <<EMAIL>>
 */

using GLib;

/**
 * Represents a type creation method.
 */
public class Vala.CreationMethod : Method {
	/**
	 * Specifies the name of the type this creation method belongs to.
	 */
	public string class_name { get; set; }

	/**
	 * Specifies the number of parameters this creation method sets.
	 */
	public int n_construction_params { get; set; }

	/**
	 * Specifies a custom C return type for that creation method.
	 * Only the idl parser and the interface writer should use this.
	 * FIXME: remove this as soon the compiler has a decent attribute
	 * handling.
	 */
	public string? custom_return_type_cname { get; set; }

	/**
	 * Specifies whether this constructor chains up to a base
	 * constructor or a different constructor of the same class.
	 */
	public bool chain_up { get; set; }

	/**
	 * Creates a new method.
	 *
	 * @param name             method name
	 * @param source_reference reference to source code
	 * @return                 newly created method
	 */
	public CreationMethod (string? class_name, string? name, SourceReference? source_reference = null) {
		base (name, new VoidType (), source_reference);
		this.class_name = class_name;

		carray_length_parameter_position = -3;
		cdelegate_target_parameter_position = -3;
	}

	public override void accept (CodeVisitor visitor) {
		visitor.visit_creation_method (this);
	}

	public override void accept_children (CodeVisitor visitor) {
		foreach (FormalParameter param in get_parameters()) {
			param.accept (visitor);
		}

		foreach (DataType error_type in get_error_types ()) {
			error_type.accept (visitor);
		}

		if (body != null) {
			body.accept (visitor);
		}
	}

	public override string get_default_cname () {
		var parent = parent_symbol as TypeSymbol;

		string infix = "new";
		if (parent is Struct) {
			infix = "init";
		}

		if (name == "new") {
			return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
		} else {
			return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
		}
	}

	public override string get_real_cname () {
		var parent = parent_symbol as Class;

		if (parent == null || parent.is_compact) {
			return get_cname ();
		}

		string infix = "construct";

		if (name == "new") {
			return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
		} else {
			return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
		}
	}

	public override bool check (SemanticAnalyzer analyzer) {
		if (checked) {
			return !error;
		}

		checked = true;

		process_attributes ();

		if (class_name != null && class_name != parent_symbol.name) {
			// class_name is null for constructors generated by GIdlParser
			Report.error (source_reference, "missing return type in method `%s.%s´".printf (analyzer.current_symbol.get_full_name (), class_name));
			error = true;
			return false;
		}

		var old_source_file = analyzer.current_source_file;
		var old_symbol = analyzer.current_symbol;
		var old_class = analyzer.current_class;
		var old_struct = analyzer.current_struct;
		var old_return_type = analyzer.current_return_type;

		if (source_reference != null) {
			analyzer.current_source_file = source_reference.file;
		}
		analyzer.current_symbol = this;
		if (parent_symbol is Class) {
			analyzer.current_class = (Class) parent_symbol;
		} else if (parent_symbol is Struct) {
			analyzer.current_struct = (Struct) parent_symbol;
		}
		analyzer.current_return_type = return_type;

		foreach (FormalParameter param in get_parameters()) {
			param.check (analyzer);
		}

		foreach (DataType error_type in get_error_types ()) {
			error_type.check (analyzer);
		}

		if (body != null) {
			body.check (analyzer);
		}

		analyzer.current_source_file = old_source_file;
		analyzer.current_symbol = old_symbol;
		analyzer.current_class = old_class;
		analyzer.current_struct = old_struct;
		analyzer.current_return_type = old_return_type;

		if (analyzer.current_symbol.parent_symbol is Method) {
			/* lambda expressions produce nested methods */
			var up_method = (Method) analyzer.current_symbol.parent_symbol;
			analyzer.current_return_type = up_method.return_type;
		}

		if (is_abstract || is_virtual || overrides) {
			Report.error (source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
			return false;
		}

		return !error;
	}
}<commit_msg>Check for unhandled errors in creation methods<commit_after>/* valacreationmethod.vala
 *
 * Copyright (C) 2007-2009  <NAME>
 * Copyright (C) 2007-2008  <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 *	<NAME> <<EMAIL>>
 * 	<NAME> <<EMAIL>>
 */

using GLib;

/**
 * Represents a type creation method.
 */
public class Vala.CreationMethod : Method {
	/**
	 * Specifies the name of the type this creation method belongs to.
	 */
	public string class_name { get; set; }

	/**
	 * Specifies the number of parameters this creation method sets.
	 */
	public int n_construction_params { get; set; }

	/**
	 * Specifies a custom C return type for that creation method.
	 * Only the idl parser and the interface writer should use this.
	 * FIXME: remove this as soon the compiler has a decent attribute
	 * handling.
	 */
	public string? custom_return_type_cname { get; set; }

	/**
	 * Specifies whether this constructor chains up to a base
	 * constructor or a different constructor of the same class.
	 */
	public bool chain_up { get; set; }

	/**
	 * Creates a new method.
	 *
	 * @param name             method name
	 * @param source_reference reference to source code
	 * @return                 newly created method
	 */
	public CreationMethod (string? class_name, string? name, SourceReference? source_reference = null) {
		base (name, new VoidType (), source_reference);
		this.class_name = class_name;

		carray_length_parameter_position = -3;
		cdelegate_target_parameter_position = -3;
	}

	public override void accept (CodeVisitor visitor) {
		visitor.visit_creation_method (this);
	}

	public override void accept_children (CodeVisitor visitor) {
		foreach (FormalParameter param in get_parameters()) {
			param.accept (visitor);
		}

		foreach (DataType error_type in get_error_types ()) {
			error_type.accept (visitor);
		}

		if (body != null) {
			body.accept (visitor);
		}
	}

	public override string get_default_cname () {
		var parent = parent_symbol as TypeSymbol;

		string infix = "new";
		if (parent is Struct) {
			infix = "init";
		}

		if (name == "new") {
			return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
		} else {
			return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
		}
	}

	public override string get_real_cname () {
		var parent = parent_symbol as Class;

		if (parent == null || parent.is_compact) {
			return get_cname ();
		}

		string infix = "construct";

		if (name == "new") {
			return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
		} else {
			return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
		}
	}

	public override bool check (SemanticAnalyzer analyzer) {
		if (checked) {
			return !error;
		}

		checked = true;

		process_attributes ();

		if (class_name != null && class_name != parent_symbol.name) {
			// class_name is null for constructors generated by GIdlParser
			Report.error (source_reference, "missing return type in method `%s.%s´".printf (analyzer.current_symbol.get_full_name (), class_name));
			error = true;
			return false;
		}

		var old_source_file = analyzer.current_source_file;
		var old_symbol = analyzer.current_symbol;
		var old_class = analyzer.current_class;
		var old_struct = analyzer.current_struct;
		var old_return_type = analyzer.current_return_type;

		if (source_reference != null) {
			analyzer.current_source_file = source_reference.file;
		}
		analyzer.current_symbol = this;
		if (parent_symbol is Class) {
			analyzer.current_class = (Class) parent_symbol;
		} else if (parent_symbol is Struct) {
			analyzer.current_struct = (Struct) parent_symbol;
		}
		analyzer.current_return_type = return_type;

		foreach (FormalParameter param in get_parameters()) {
			param.check (analyzer);
		}

		foreach (DataType error_type in get_error_types ()) {
			error_type.check (analyzer);
		}

		if (body != null) {
			body.check (analyzer);
		}

		analyzer.current_source_file = old_source_file;
		analyzer.current_symbol = old_symbol;
		analyzer.current_class = old_class;
		analyzer.current_struct = old_struct;
		analyzer.current_return_type = old_return_type;

		if (analyzer.current_symbol.parent_symbol is Method) {
			/* lambda expressions produce nested methods */
			var up_method = (Method) analyzer.current_symbol.parent_symbol;
			analyzer.current_return_type = up_method.return_type;
		}

		if (is_abstract || is_virtual || overrides) {
			Report.error (source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
			return false;
		}

		// check that all errors that can be thrown in the method body are declared
		if (body != null) {
			foreach (DataType body_error_type in body.get_error_types ()) {
				bool can_propagate_error = false;
				foreach (DataType method_error_type in get_error_types ()) {
					if (body_error_type.compatible (method_error_type)) {
						can_propagate_error = true;
					}
				}
				if (!can_propagate_error) {
					Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
				}
			}
		}

		return !error;
	}
}
{'fraction_non_alphanumeric': 0.09893674535952424, 'fraction_numerical': 0.00558659217877095, 'mean_word_length': 3.775817555938038, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3369793', 'n_tokens_mistral': 3775, 'n_tokens_neox': 3348, 'n_words': 1075}