[valadoc] libvaladoc/html: Add "All known members inherited from "



commit 3ca94cabb68789cb20e37e0c9ecea7acc8b9487e
Author: Florian Brosch <flo brosch gmail com>
Date:   Fri Aug 10 01:48:45 2012 +0200

    libvaladoc/html: Add "All known members inherited from "

 src/libvaladoc/api/class.vala        |    2 +-
 src/libvaladoc/api/interface.vala    |    3 +-
 src/libvaladoc/api/node.vala         |   38 ++++++++-
 src/libvaladoc/html/basicdoclet.vala |  161 ++++++++++++++++++++++++++++++++--
 4 files changed, 192 insertions(+), 12 deletions(-)
---
diff --git a/src/libvaladoc/api/class.vala b/src/libvaladoc/api/class.vala
index 6c19ea0..6eec137 100644
--- a/src/libvaladoc/api/class.vala
+++ b/src/libvaladoc/api/class.vala
@@ -160,7 +160,7 @@ public class Valadoc.Api.Class : TypeSymbol {
 	 */
 	public Collection<TypeReference> get_full_implemented_interface_list () {
 		if (_full_implemented_interfaces == null) {
-			_full_implemented_interfaces = new HashSet<TypeReference> ();
+			_full_implemented_interfaces = new LinkedList<TypeReference> ();
 			_full_implemented_interfaces.add_all (this.interfaces);
 
 			if (base_type != null) {
diff --git a/src/libvaladoc/api/interface.vala b/src/libvaladoc/api/interface.vala
index b8c339e..51b6e00 100644
--- a/src/libvaladoc/api/interface.vala
+++ b/src/libvaladoc/api/interface.vala
@@ -67,9 +67,10 @@ public class Valadoc.Api.Interface : TypeSymbol {
 	/**
 	 * Returns a list of all preconditioned interfaces
 	 */
+	// TODO: rename to get_full_...
 	public Collection<TypeReference> get_all_implemented_interface_list () {
 		if (_full_implemented_interfaces == null) {
-			_full_implemented_interfaces = new HashSet<TypeReference> ();
+			_full_implemented_interfaces = new LinkedList<TypeReference> ();
 			_full_implemented_interfaces.add_all (this.interfaces);
 
 			if (base_type != null) {
diff --git a/src/libvaladoc/api/node.vala b/src/libvaladoc/api/node.vala
index e28a898..8c5345c 100644
--- a/src/libvaladoc/api/node.vala
+++ b/src/libvaladoc/api/node.vala
@@ -144,6 +144,7 @@ public abstract class Valadoc.Api.Node : Item, Browsable, Documentation, Compara
 	private Map<string,Node> per_name_children;
 	private Map<NodeType?, Gee.List<Node>> per_type_children;
 
+
 	public Node (Node? parent, SourceFile? file, string? name, void* data) {
 		base (data);
 
@@ -165,6 +166,7 @@ public abstract class Valadoc.Api.Node : Item, Browsable, Documentation, Compara
 	/**
 	 * { inheritDoc}
 	 */
+	// TODO: rename to is_visible
 	public abstract bool is_browsable (Settings settings);
 
 	/**
@@ -211,12 +213,45 @@ public abstract class Valadoc.Api.Node : Item, Browsable, Documentation, Compara
 	}
 
 	/**
+	 * Specifies whether this node has at least one visible child with the given type
+	 *
+	 * @param type a node type
+	 */
+	public bool has_visible_children_by_type (NodeType type, Settings settings) {
+		Gee.List<Node>? all_children = per_type_children.get (type);
+		if (all_children != null) {
+			foreach (Node node in all_children) {
+				if (node.is_browsable (settings)) {
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+	/**
+	 * Specifies whether this node has at least one visible child with the given types
+	 *
+	 * @param types a list of node types
+	 */
+	public bool has_visible_children_by_types (NodeType[] types, Settings settings) {
+		foreach (NodeType type in types) {
+			if (has_visible_children_by_type (type, settings)) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	/**
 	 * Specifies whether this node has at least one child with the given type
 	 *
 	 * @param type a node type
 	 */
 	public bool has_children_by_type (NodeType type) {
-		Gee.List<Node> all_children = per_type_children.get (type);
+		Gee.List<Node>? all_children = per_type_children.get (type);
 		return all_children != null && !all_children.is_empty;
 	}
 
@@ -306,6 +341,7 @@ public abstract class Valadoc.Api.Node : Item, Browsable, Documentation, Compara
 	 * Visits all children of this node with the specified Visitor.
 	 *
 	 * @param visitor the visitor to be called while traversing
+	 * @param filtered specifies whether nodes which are not browsable should appear in the list
 	 */
 	public void accept_all_children (Visitor visitor, bool filtered = true) {
 		foreach (Gee.List<Node> children in per_type_children.values) {
diff --git a/src/libvaladoc/html/basicdoclet.vala b/src/libvaladoc/html/basicdoclet.vala
index 4f6d7c2..c63edc7 100644
--- a/src/libvaladoc/html/basicdoclet.vala
+++ b/src/libvaladoc/html/basicdoclet.vala
@@ -128,6 +128,25 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 	}
 
 
+	private TypeSymbol? unpack_type_reference (TypeReference? type_reference) {
+		Api.Item pos = type_reference;
+
+		while (pos != null) {
+			if (pos is TypeReference) {
+				pos = ((TypeReference) pos).data_type;
+			} else if (pos is Api.Array) {
+				pos = ((Api.Array) pos).data_type;
+			} else if (pos is Pointer) {
+				pos = ((Pointer) pos).data_type;
+			} else {
+				assert (pos is TypeSymbol);
+				return (TypeSymbol) pos;
+			}
+		}
+
+		return null;
+	}
+
 
 	protected void write_navi_entry_html_template (string style, string content, bool is_deprecated) {
 		writer.start_tag ("li", {"class", style});
@@ -536,7 +555,7 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 		return list;
 	}
 
-	private void write_known_symbols_node (Gee.Collection<Api.Node> nodes2, Api.Node container, string headline) {
+	private void write_known_symbols_note (Gee.Collection<Api.Node> nodes2, Api.Node container, string headline) {
 		var nodes = get_accessible_nodes_from_list (nodes2);
 		if (nodes.size == 0) {
 			return ;
@@ -578,7 +597,12 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 			for (int p = 0; p < list_sizes[i] && iter.next (); p++) {
 				var node = iter.get ();
 				writer.start_tag ("li", {"class", cssresolver.resolve (node)});
-				writer.link (get_link (node, container), node.name);
+				string link = get_link (node, container);
+				if (link == null) {
+					writer.text (node.name);
+				} else {
+					writer.link (link, node.name);
+				}
 				writer.end_tag ("li");
 			}
 
@@ -607,13 +631,15 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 
 		if (node is Class) {
 			var cl = node as Class;
-			write_known_symbols_node (cl.get_known_child_classes (), cl, "All known sub-classes:");
-			write_known_symbols_node (cl.get_known_derived_interfaces (), cl, "Required by:");
+			write_known_symbols_note (cl.get_known_child_classes (), cl, "All known sub-classes:");
+			write_known_symbols_note (cl.get_known_derived_interfaces (), cl, "Required by:");
 		} else if (node is Interface) {
 			var iface = node as Interface;
-			write_known_symbols_node (iface.get_known_implementations (), iface, "All known implementing classes:");
-			write_known_symbols_node (iface.get_known_related_interfaces (), iface, "All known sub-interfaces:");
+			write_known_symbols_note (iface.get_known_implementations (), iface, "All known implementing classes:");
+			write_known_symbols_note (iface.get_known_related_interfaces (), iface, "All known sub-interfaces:");
 		}
+		// TODO: All known sub-structs
+
 
 		if (node.parent is Namespace) {
 			writer.simple_tag ("br");
@@ -621,7 +647,9 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 			write_package_note (node);
 		}
 
-		if (!(node is Method || node is Delegate || node is Api.Signal)) { // avoids exception listings & implementations
+		if (!(node is Method || node is Delegate || node is Api.Signal)) {
+			// avoids exception listings & implementations
+
 			if (node.has_children ({
 					Api.NodeType.ERROR_CODE,
 					Api.NodeType.ENUM_VALUE,
@@ -653,9 +681,124 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 				write_children (node, Api.NodeType.FIELD, "Fields", node);
 			}
 		}
+
+		if (node is Class) {
+			write_inherited_symbols_note_for_class ((Class) node, node);
+		} else if (node is Interface) {
+			write_inherited_symbols_note_for_interface ((Interface) node, node);
+		} else if (node is Struct) {
+			write_inherited_symbols_note_for_struct ((Struct) node, node);
+		}
+
 		writer.end_tag ("div");
 	}
 
+	private static NodeType[] inheritable_members = {
+			NodeType.CONSTANT,
+			NodeType.PROPERTY,
+			NodeType.DELEGATE,
+			NodeType.STATIC_METHOD,
+			NodeType.METHOD,
+			NodeType.SIGNAL,
+			NodeType.FIELD,
+		};
+
+	private inline bool has_visible_inheritable_children (TypeSymbol symbol) {
+		return symbol.has_visible_children_by_types (inheritable_members, _settings);
+	}
+
+	private void write_inherited_members_headline () {
+		writer.start_tag ("h3", {"class", css_title}).text ("Inherited Members:").end_tag ("h3");
+	}
+
+	private void write_inherited_symbols_note_for_class (Class cl, Api.Node container) {
+		bool headline_printed = false;
+
+		// class hierarchy:
+		Class base_class = unpack_type_reference (cl.base_type) as Class;
+		while (base_class != null) {
+			if (!headline_printed && has_visible_inheritable_children (base_class)) {
+				write_inherited_members_headline ();
+				headline_printed = true;
+			}
+
+			write_inherited_symbols_note (base_class, "class", container);
+			base_class = unpack_type_reference (base_class.base_type) as Class;
+		}
+
+
+		// implemented interfaces
+		Gee.LinkedList<Interface> printed_interfaces = new Gee.LinkedList<Interface> ();
+		foreach (TypeReference iface_ref in cl.get_full_implemented_interface_list ()) {
+			Interface iface = (Interface) unpack_type_reference (iface_ref);
+
+			if (!headline_printed && has_visible_inheritable_children (iface)) {
+				write_inherited_members_headline ();
+				headline_printed = true;
+			} else if (printed_interfaces.contains (iface)) {
+				continue ;
+			}
+
+			write_inherited_symbols_note (iface, "interface", container);
+			printed_interfaces.add (iface);
+		}
+	}
+
+	private void write_inherited_symbols_note_for_interface (Interface iface, Api.Node container) {
+		bool headline_printed = false;
+
+		// class hierarchy:
+		Class base_class = unpack_type_reference (iface.base_type) as Class;
+		while (base_class != null) {
+			if (!headline_printed && has_visible_inheritable_children (base_class)) {
+				write_inherited_members_headline ();
+				headline_printed = true;
+			}
+
+			write_inherited_symbols_note (base_class, "class", container);
+			base_class = unpack_type_reference (base_class.base_type) as Class;
+		}
+
+
+		// interfaces:
+		Gee.LinkedList<Interface> printed_interfaces = new Gee.LinkedList<Interface> ();
+		foreach (TypeReference pre_ref in iface.get_all_implemented_interface_list ()) {
+			Interface pre = (Interface) unpack_type_reference (pre_ref);
+
+			if (!headline_printed && has_visible_inheritable_children (pre)) {
+				write_inherited_members_headline ();
+				headline_printed = true;
+			} else if (printed_interfaces.contains (pre)) {
+				continue ;
+			}
+
+			write_inherited_symbols_note (pre, "interface", container);
+			printed_interfaces.add (pre);
+		}
+	}
+
+	private void write_inherited_symbols_note_for_struct (Struct str, Api.Node container) {
+		Struct base_struct = unpack_type_reference (str.base_type) as Struct;
+		if (base_struct != null && has_visible_inheritable_children (base_struct)) {
+			write_inherited_members_headline ();
+			write_inherited_symbols_note (base_struct, "struct", container);
+		}
+	}
+
+	private void write_inherited_symbols_note (TypeSymbol symbol, string type, Api.Node container) {
+		write_known_symbols_note (symbol.get_children_by_types (inheritable_members, false), container, "All known members inherited from %s %s".printf (type, symbol.get_full_name ()));
+
+		/*
+		write_known_symbols_note (symbol.get_children_by_type (NodeType.CONSTANT, false), container, "All known constants inherited from %s %s".printf (type, symbol.get_full_name ()));
+		write_known_symbols_note (symbol.get_children_by_type (NodeType.PROPERTY, false), container, "All known properties inherited from %s %s".printf (type, symbol.get_full_name ()));
+		write_known_symbols_note (symbol.get_children_by_type (NodeType.DELEGATE, false), container, "All known delegates inherited from %s %s".printf (type, symbol.get_full_name ()));
+		write_known_symbols_note (symbol.get_children_by_type (NodeType.STATIC_METHOD, false), container, "All known static methods inherited from %s %s".printf (type, symbol.get_full_name ()));
+		write_known_symbols_note (symbol.get_children_by_type (NodeType.METHOD, false), container, "All known methods inherited from %s %s".printf (type, symbol.get_full_name ()));
+		write_known_symbols_note (symbol.get_children_by_type (NodeType.SIGNAL, false), container, "All known signals inherited from %s %s".printf (type, symbol.get_full_name ()));
+		write_known_symbols_note (symbol.get_children_by_type (NodeType.FIELD, false), container, "All known fields inherited from  %s %s".printf (type, symbol.get_full_name ()));
+		*/
+	}
+
 	protected void write_child_namespaces (Api.Node node, Api.Node? parent) {
 		Gee.ArrayList<Namespace> namespaces = new Gee.ArrayList<Namespace> ();
 		this.fetch_subnamespace_names (node, namespaces);
@@ -698,7 +841,7 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 	}
 
 	protected void write_child_dependencies (Package package, Api.Node? parent) {
-		Gee.Collection<Package> deps = package.get_full_dependency_list ();
+		Gee.Collection<Package>? deps = package.get_full_dependency_list ();
 		if (deps.size == 0) {
 			return;
 		}
@@ -706,7 +849,7 @@ public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
 		writer.start_tag ("h2", {"class", css_title}).text ("Dependencies:").end_tag ("h2");
 		writer.start_tag ("ul", {"class", css_inline_navigation});
 		foreach (Package p in deps) {
-			string link = this.get_link (p, parent);
+			string? link = this.get_link (p, parent);
 			if (link == null) {
 				writer.start_tag ("li", {"class", cssresolver.resolve (p), "id", p.name}).text (p.name).end_tag ("li");
 			} else {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]