note description: "Routines intended for use by DOCUMENTATION." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" deferred class DOCUMENTATION_ROUTINES inherit DOCUMENTATION_EXPORT OUTPUT_ROUTINES EIFFEL_PROJECT_FACILITIES EC_SHARED_PREFERENCES INTERNAL_COMPILER_STRING_EXPORTER feature -- Status setting set_excluded_indexing_items (l: like excluded_indexing_items) -- Assign `l' to `excluded_indexing_items'. do excluded_indexing_items := l end feature -- Access current_class: CLASS_C -- Class currently being processed. excluded_indexing_items: LINEAR [STRING_32] -- Indexing items not to include in HTML meta clause. index_text (a_text_formatter: TEXT_FORMATTER) -- Generate documentation index as structured text. require a_text_formatter_not_void: a_text_formatter /= Void local subs: ARRAYED_LIST [CONF_GROUP] do a_text_formatter.process_filter_item (f_class_declaration, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, True, True) a_text_formatter.process_filter_item (f_menu_bar, False) append_system_info (a_text_formatter) subs := top_level_clusters if subs /= Void and then not subs.is_empty then a_text_formatter.process_keyword_text ("Top-level clusters", Void) a_text_formatter.add_new_line append_cluster_list (a_text_formatter, subs) a_text_formatter.add_new_line end a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, True, True) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_filter_item (f_class_declaration, False) end class_list_text (du: DOCUMENTATION_UNIVERSE; a_text_formatter: TEXT_FORMATTER) -- Generate documentation class list from `du.classes' as structured text. require du_not_void: du /= Void a_text_formatter_not_void: a_text_formatter /= Void do a_text_formatter.process_filter_item (f_class_declaration, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, False, True, True) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_keyword_text ("Classes", Void) a_text_formatter.add_new_line append_class_list (a_text_formatter, du.classes, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, False, True, True) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_filter_item (f_class_declaration, False) end cluster_list_text (du: DOCUMENTATION_UNIVERSE; a_text_formatter:TEXT_FORMATTER) -- Generate documentation cluster list from `du.clusters' as structured text. require du_not_void: du /= Void a_text_formatter_not_void: a_text_formatter /= Void do a_text_formatter.process_filter_item (f_class_declaration, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, False, True) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_keyword_text ("Clusters", Void) a_text_formatter.add_new_line append_cluster_list (a_text_formatter, du.groups) a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, False, True) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_filter_item (f_class_declaration, False) end cluster_hierarchy_text (du: DOCUMENTATION_UNIVERSE; a_text_formatter: TEXT_FORMATTER) -- Generate documentation cluster hierarchy as structured text. -- Do not generate leafs of clusters that are not generated as described by `du'. -- Add links to diagrams if `diagrams' is True. require du_not_void: du /= Void a_text_formatter_not_void: a_text_formatter /= Void local group: CONF_GROUP do a_text_formatter.process_filter_item (f_class_declaration, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, True, False) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_keyword_text ("Clusters", Void) a_text_formatter.add_new_line across eiffel_universe.target.groups as gs loop group := gs.item if attached {CONF_CLUSTER} group as l_cluster implies not attached l_cluster.parent then append_cluster_hierarchy_leaf (a_text_formatter, du, group, 1) end end a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, True, False) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_filter_item (f_class_declaration, False) end group_index_text ( group: CONF_GROUP; class_list: ARRAYED_LIST [CLASS_I]; diagrams: BOOLEAN; a_text_formatter: TEXT_FORMATTER ) -- Generate documentation group index for `group'. -- Add links to diagrams if `diagrams' is True. require group_not_void: group /= Void a_text_formatter_not_void: a_text_formatter /= Void local l_name: STRING_32 l_group_type: STRING_32 l_desc: detachable READABLE_STRING_32 do l_group_type := type_of_group (group) l_name := group_name_presentation ({STRING_32}".", {STRING_32}"", group) a_text_formatter.process_filter_item (f_class_declaration, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, True, False) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_keyword_text (l_group_type, Void) a_text_formatter.add_new_line a_text_formatter.add_indent a_text_formatter.process_cluster_name_text (l_name, group, False) if diagrams then a_text_formatter.add_indent a_text_formatter.process_string_text ("(diagram)", "./diagram.html") end a_text_formatter.add_new_line a_text_formatter.add_new_line; -- Generate indexes for a group. -- We may need more structured information for indexing of a group. a_text_formatter.process_keyword_text (ti_indexing_keyword, Void) a_text_formatter.process_new_line a_text_formatter.add_indent a_text_formatter.process_basic_text ("description") a_text_formatter.process_symbol_text (ti_colon) a_text_formatter.process_basic_text (ti_space) a_text_formatter.process_string_text (ti_double_quote, Void) l_desc := Void if group.is_library and then attached {CONF_LIBRARY} group as l_library and then l_library.classes_set then l_desc := l_library.library_target.description else l_desc := group.description end if l_desc /= Void then a_text_formatter.add_indexing_string (l_desc) end a_text_formatter.process_string_text (ti_double_quote, Void) a_text_formatter.process_new_line if attached group.target.version as l_version and then attached l_version.copyright as l_version_copyright then a_text_formatter.add_indent a_text_formatter.process_basic_text ("copyright") a_text_formatter.process_symbol_text (ti_colon) a_text_formatter.process_basic_text (ti_space) a_text_formatter.process_string_text (ti_double_quote, Void) a_text_formatter.add_indexing_string (l_version_copyright) a_text_formatter.process_string_text (ti_double_quote, Void) a_text_formatter.process_new_line end a_text_formatter.process_new_line if group.is_cluster and then attached {CONF_CLUSTER} group as l_cluster and then attached l_cluster.parent as l_cluster_parent then a_text_formatter.process_keyword_text ("Supercluster", Void) a_text_formatter.add_new_line a_text_formatter.add_indent a_text_formatter.process_cluster_name_text (group_name_presentation ({STRING_32}".", {STRING_32}"", l_cluster_parent), l_cluster_parent, False) a_text_formatter.add_new_line a_text_formatter.add_new_line end if attached subclusters_of_group (group) as subs and then not subs.is_empty then a_text_formatter.process_keyword_text ("Subclusters", Void) a_text_formatter.add_new_line append_cluster_list (a_text_formatter, subs) a_text_formatter.add_new_line end if not class_list.is_empty then a_text_formatter.process_keyword_text ("Classes", Void) a_text_formatter.add_new_line append_class_list (a_text_formatter, class_list, False) end a_text_formatter.process_filter_item (f_menu_bar, True) insert_global_menu_bar (a_text_formatter, True, True, False) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_filter_item (f_class_declaration, False) end class_chart_text (class_c: CLASS_C; a_text_formatter: TEXT_FORMATTER) -- Generate documentation class chart for `class_c' as structured text. require class_c_not_void: class_c /= Void a_text_formatter_not_void: a_text_formatter /= Void local as_c: CLASS_C features: LINEAR [E_FEATURE] queries, commands, actions: SORTED_TWO_WAY_LIST [E_FEATURE] f: E_FEATURE do current_class := class_c a_text_formatter.process_filter_item (f_class_declaration, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_class_menu_bar (a_text_formatter, {UTF_CONVERTER}.utf_8_string_8_to_string_32 (class_c.name).as_lower) a_text_formatter.process_filter_item (f_menu_bar, False) class_c.append_header (a_text_formatter) a_text_formatter.add_new_line append_general_info (a_text_formatter, class_c.original_class) append_class_ancestors (a_text_formatter, class_c) create queries.make create commands.make create actions.make as_c := Action_sequence_class features := class_c.api_feature_table.linear_representation if features /= Void then from features.start until features.after loop f := features.item if display_feature (f, class_c) then if f.is_procedure then commands.extend (f) elseif safe_conforms_to (f, as_c) then actions.extend (f) else queries.extend (f) end end features.forth end end append_feature_chart_item (a_text_formatter, actions, "Action sequences") append_feature_chart_item (a_text_formatter, queries, "Queries") append_feature_chart_item (a_text_formatter, commands, "Commands") append_class_constraints (a_text_formatter, class_c) a_text_formatter.process_filter_item (f_menu_bar, True) insert_class_menu_bar (a_text_formatter, {UTF_CONVERTER}.utf_8_string_8_to_string_32 (class_c.name).as_lower) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_filter_item (f_class_declaration, False) current_class := Void end class_relations_text (class_c: CLASS_C; a_text_formatter: TEXT_FORMATTER) -- Generate documentation class relations for `class_c' as structured text. require class_c_not_void: class_c /= Void a_text_formatter_not_void: a_text_formatter /= Void do a_text_formatter.process_filter_item (f_class_declaration, True) a_text_formatter.process_filter_item (f_menu_bar, True) insert_class_menu_bar (a_text_formatter, {UTF_CONVERTER}.utf_8_string_8_to_string_32 (class_c.name).as_lower) a_text_formatter.process_filter_item (f_menu_bar, False) class_c.append_header (a_text_formatter) a_text_formatter.add_new_line append_class_ancestors (a_text_formatter, class_c) append_class_descendants (a_text_formatter, class_c) append_class_clients (a_text_formatter, class_c) append_class_suppliers (a_text_formatter, class_c) a_text_formatter.process_filter_item (f_menu_bar, True) insert_class_menu_bar (a_text_formatter, {UTF_CONVERTER}.utf_8_string_8_to_string_32 (class_c.name).as_lower) a_text_formatter.process_filter_item (f_menu_bar, False) a_text_formatter.process_filter_item (f_class_declaration, False) end class_text (class_c: CLASS_C; flat, short: BOOLEAN; a_text_formatter: TEXT_FORMATTER) -- Generate documentation class text for `class_c' as structured text. require class_c_not_void: class_c /= Void local formatter: CLASS_TEXT_FORMATTER do create formatter formatter.set_documentation (Current) formatter.set_clickable if flat then formatter.set_feature_clause_order (preferences.flat_short_data.feature_clause_order) else formatter.set_one_class_only formatter.set_order_same_as_text end if short then formatter.set_is_short end formatter.format (class_c, a_text_formatter) end feature -- Routines append_general_info (text: TEXT_FORMATTER; class_i: CLASS_I) -- Append "General" item for class charts. local s: STRING_32 class_c: CLASS_C l_group: CONF_GROUP do class_c := class_i.compiled_class text.process_keyword_text ("General", Void) text.add_new_line if class_c.is_obsolete then append_info_item (text, "obsolete") add_string_multilined (text, "%"" + class_c.obsolete_message + "%"") text.add_new_line end if attached {EXTERNAL_CLASS_I} class_i as l_external_class then append_info_item (text, "dotnet name") text.process_string_text (l_external_class.dotnet_name, Void) text.add_new_line end l_group := class_i.group s := type_of_group (l_group) append_info_item (text, s.as_lower) text.process_cluster_name_text (l_group.name, l_group, False) text.add_new_line s := indexing_item_as_string (class_i, "description") if s /= Void then append_info_item (text, "description") add_string_multilined (text, s) text.add_new_line end s := indexing_item_as_string (class_i, "keywords") if s /= Void then append_info_item (text, "keywords") add_string_multilined (text, s) text.add_new_line end if attached class_c.creators as cs and then not cs.is_empty then append_info_item (text, "create") append_creators (text, class_c) text.add_new_line end text.add_new_line end append_class_constraints (text: TEXT_FORMATTER; class_c: CLASS_C) -- Append to `text', all invariant tags. local ast: INVARIANT_AS invariants: EIFFEL_LIST [TAGGED_AS] s: STRING_32 do ast := class_c.invariant_ast if ast /= Void then invariants := ast.assertion_list if attached ast.assertion_list as l_assertion_list and then not l_assertion_list.is_empty then text.process_keyword_text ("Constraints", Void) text.add_new_line from invariants.start until invariants.after loop if attached invariants.item.tag as l_tag then s := l_tag.name_32 end if s /= Void and then not s.is_empty then create s.make_from_string (s) s.replace_substring_all ({STRING_32} "_", {STRING_32} " ") text.add_indent text.process_assertion_tag_text (s) text.add_new_line end invariants.forth end text.add_new_line end end end append_creators (text: TEXT_FORMATTER; class_c: CLASS_C) -- Append creators list. local f: E_FEATURE do if attached class_c.creators as cs then across cs as c loop f := class_c.feature_with_name_id (c.key) text.add_feature (f, f.name_32) if not c.is_last then text.process_symbol_text (ti_Comma) text.add_space end end end end append_cluster_list (text: TEXT_FORMATTER; cluster_list: ARRAYED_LIST [CONF_GROUP]) local l_cluster: CONF_GROUP do from cluster_list.start until cluster_list.after loop text.add_indent l_cluster := cluster_list.item_for_iteration text.process_cluster_name_text (group_name_presentation (".", "", l_cluster), l_cluster, False) text.add_new_line cluster_list.forth end end append_feature_list (text: TEXT_FORMATTER; f_list: LINEAR [E_FEATURE]) -- Append list of feature with signatures to `ctxt'. local f: E_FEATURE t: STRING_32 wc: CLASS_C do from f_list.start until f_list.after loop f := f_list.item t := feature_tooltip (f) text.add_indent text.process_tooltip_item (t, True) f.append_signature (text) text.process_tooltip_item (t, False) wc := f.written_class if current_class /= wc then text.process_filter_item (f_Origin_comment, True) text.add_comment_text (" -- (from " + wc.name_in_upper + ")") text.process_filter_item (f_Origin_comment, False) end text.add_new_line f_list.forth end end feature_tooltip (f: E_FEATURE): STRING_32 -- Get a descriptive comment on the origin of `f'. local wc: CLASS_C real_name: STRING_32 do create Result.make (20) Result.append_character ({CHARACTER_32}'`') Result.append (f.name_32) Result.append_character ({CHARACTER_32}'%'') Result.append_character ({CHARACTER_32}' ') if attached f.written_feature as anc then real_name := anc.name_32 else real_name := f.name_32 end wc := f.written_class if wc = current_class then Result.append_string_general ("is declared in `Current'") else Result.append ({STRING_32}"was declared in ") Result.append_string_general (wc.name_in_upper) if not real_name.same_string (f.name_32) then Result.append_string_general (" as `") Result.append (real_name) Result.append_character ({CHARACTER_32}'%'') end end end feature {NONE} -- Implementation append_class_list (text: TEXT_FORMATTER; class_list: ARRAYED_LIST [CLASS_I]; desc: BOOLEAN) -- Append to `ctxt.text', formatted `class_list'. -- Depending on `desc', include descriptions. local s: detachable STRING_32 ci: CLASS_I do across class_list as c loop ci := c.item text.add_indent ci.compiled_class.append_signature (text, True) text.add_new_line if desc then s := indexing_item_as_string (ci, "description") if s /= Void then create s.make_from_string (s) s.remove (1) s.remove (s.count) s.replace_substring_all ({STRING_32} "%%T", {STRING_32} "") s.replace_substring_all ({STRING_32} "%%R", {STRING_32} "") s.replace_substring_all ({STRING_32} "%%%'", {STRING_32} "%'") s.replace_substring_all ({STRING_32} "%%%"", {STRING_32} "%"") append_comment (text, s) end text.add_new_line end end end append_cluster_hierarchy_leaf (text: TEXT_FORMATTER; du: DOCUMENTATION_UNIVERSE; a_group: CONF_GROUP; indent: INTEGER) local n: INTEGER do from n := 1 until n > indent loop text.add_indent n := n + 1 end if du.is_group_generated (a_group) then text.process_cluster_name_text (a_group.name, a_group, False) else text.process_basic_text (a_group.name) end text.add_new_line if attached subclusters_of_group (a_group) as subs then from subs.start until subs.after loop append_cluster_hierarchy_leaf (text, du, subs.item_for_iteration, indent + 1) subs.forth end end end add_string_multilined (text: TEXT_FORMATTER; s: STRING_32) -- Append `s' to `text' using the multilined formatting. local sb: STRING_32 n, ind: INTEGER do if s.substring_index ("%%N", 1) > 0 then -- Format on a new line, breaking at every newline. -- Indent `ind' times. -- Prune all '%' and special characters. ind := 2 text.add_new_line text.add_indents (ind) s.replace_substring_all ({STRING_32} "%%T", {STRING_32} "") s.replace_substring_all ({STRING_32} "%%R", {STRING_32} "") n := s.substring_index ("%%N", 1) text.add_indexing_string (s.substring (1, n - 1)) text.add_new_line text.add_indents (ind) s.remove_head (n + 1) from n := s.substring_index ("%%N", 1) until n = 0 loop if n = 0 then n := s.count else n := n + 1 end sb := s.substring (1, n - 2) s.remove_head (n) text.add_indexing_string (sb) text.add_new_line text.add_indents (ind) n := s.substring_index ("%%N", 1) end text.add_indexing_string (s) else text.add_indexing_string (s) end end append_info_item (text: TEXT_FORMATTER; tag: STRING_32) -- Append `tag': `content' to `text'. do text.add_indent text.process_indexing_tag_text (tag) text.process_symbol_text (ti_Colon) text.add_space end append_feature_chart_item (text: TEXT_FORMATTER; fl: LIST [E_FEATURE]; a_title: STRING_32) -- Append class ancestors for `class_c' to `text'. do if not fl.is_empty then text.process_keyword_text (a_title, Void) text.add_new_line append_feature_list (text, fl) text.add_new_line end end append_comment (text: TEXT_FORMATTER; comment: STRING_32) -- Append `comment' to `text'. local n, prev: INTEGER do from n := 1 prev := n until n = 0 loop n := comment.substring_index ("%%N", prev) text.add_indent text.add_indent text.add_indent text.add_comment_text (ti_Dashdash) if n > 0 then text.add_comment_text ({STRING_32} " " + comment.substring (prev, n - 1)) prev := n + 2 else text.add_comment_text ({STRING_32} " " + comment.substring (prev, comment.count)) end text.add_new_line end end feature {NONE} -- Indexing clauses html_meta_for_class (a_class: CLASS_I): STRING_32 -- Generate string with list of HTML META tags -- describing the indexing clause of `a_class'. require a_class_not_void: a_class /= Void a_class_is_compiled: a_class.is_compiled local cl: CLASS_C do cl := a_class.compiled_class Result := indexes_to_html_meta (cl.ast.top_indexes, "Eiffel class") Result.append (indexes_to_html_meta (cl.ast.bottom_indexes, "Eiffel class")) end html_meta_for_cluster (cluster_i: CONF_GROUP): STRING_32 -- Generate strings of HTML meta data. require cluster_i_not_void: cluster_i /= Void do Result := indexes_to_html_meta_group (cluster_i, "Eiffel cluster") end html_meta_for_system: STRING_32 -- Generate strings of HTML meta data. do Result := indexing_tuple_to_string ("keywords", "Eiffel system") end indexes_to_html_meta_group (a_group: CONF_GROUP; added_keywords: STRING_32): STRING_32 -- Convert `a_group' to a big string of HTML meta data. local content, t: STRING_32 exc: like excluded_indexing_items l_description: detachable READABLE_STRING_32 do create Result.make (20) exc := excluded_indexing_items if a_group.is_library and then attached {CONF_LIBRARY} a_group as l_library and then l_library.classes_set then l_description := l_library.library_target.description end if l_description = Void then l_description := a_group.description end if l_description /= Void then t := "description" content := l_description content.replace_substring_all ({STRING_32} "%%N", {STRING_32} " ") content.prune_all ('%%') content.prune_all ('"') Result.append (indexing_tuple_to_string (t, content)) end if attached a_group.target.version as l_version and then attached l_version.copyright as l_version_copyright then t := "copyright" create content.make_from_string_general (l_version_copyright) content.replace_substring_all ({STRING_32} "%%N", {STRING_32} " ") content.prune_all ('%%') content.prune_all ('"') Result.append (indexing_tuple_to_string (t, content)) end if not exc.has ({STRING_32} "keywords") and added_keywords /= Void then Result.append (indexing_tuple_to_string ("keywords", added_keywords)) end end indexes_to_html_meta (indexes: EIFFEL_LIST [INDEX_AS]; added_keywords: STRING_32): STRING_32 -- Convert `indexes' to a big string of HTML meta data. local content, t: STRING_32 ic: HASH_TABLE [STRING_32, STRING_32] exc: like excluded_indexing_items do create Result.make (20) ic := indexes_to_table (indexes) exc := excluded_indexing_items from exc.start until exc.after loop ic.remove (exc.item) exc.forth end from ic.start until ic.after loop t := ic.key_for_iteration content := ic.item_for_iteration.twin content.replace_substring_all ({STRING_32} "%%N", {STRING_32} " ") content.prune_all ('%%') content.prune_all ('"') if t.same_string_general ("keywords") and added_keywords /= Void then content.prepend_string_general (", ") content.prepend (added_keywords) end Result.append (indexing_tuple_to_string (t, content)) ic.forth end if not ic.has ({STRING_32} "keywords") and not exc.has ({STRING_32} "keywords") and added_keywords /= Void then Result.append (indexing_tuple_to_string ("keywords", added_keywords)) end end indexing_tuple_to_string (tag, content: STRING_32): STRING_32 -- Create HTML meta string. do create Result.make (20) Result.append_string_general ("%N") end indexes_to_table (indexes: detachable EIFFEL_LIST [INDEX_AS]): HASH_TABLE [STRING_32, STRING_32] -- Table of [content, tag]. local t: STRING_32 ii: INDEX_AS do create Result.make (5) if indexes /= Void then from indexes.start until indexes.after loop ii := indexes.item if attached ii.tag as l_tag then t := l_tag.name_32 end if t = Void then t := {STRING_32} "description" -- It is legal Eiffel syntax to omit first tag -- of the indexing clause. -- We will assume this is the description clause. end Result.put (ii.content_as_string_32, t) indexes.forth end end end indexing_item_as_string (c: CLASS_I; s: STRING_32): STRING_32 local ic: HASH_TABLE [STRING_32, STRING_32] do ic := indexes_to_table (c.compiled_class.ast.top_indexes) if ic.has_key (s) then Result := ic.found_item end if Result = Void then ic := indexes_to_table (c.compiled_class.ast.bottom_indexes) if ic.has_key (s) then Result := ic.found_item end end end feature {NONE} -- Implementation safe_conforms_to (f: E_FEATURE; conf: CLASS_C): BOOLEAN -- Is the return type of `f' a descendant of `conf'? -- `f' may be any feature. Returns `False' if not a function. require f_not_void: f /= Void do Result := attached f.type as t and then t.has_associated_class and then attached t.base_class as return_class and then attached conf and then return_class.conform_to (conf) end Action_sequence_class: CLASS_C -- Compiled class ACTION_SEQUENCE. do if attached Eiffel_system.Universe.compiled_classes_with_name ("ACTION_SEQUENCE") as cl and then not cl.is_empty then Result := cl.first.compiled_class end end Any_class: CLASS_C -- Compiled class ANY. once Result := Eiffel_system.any_class.compiled_class end display_feature (f: E_FEATURE; class_c: CLASS_C): BOOLEAN -- Should feature be included in feature list for `class_c'? do Result := f.is_exported_to (Any_class) and then (class_c = Any_class or else f.written_class /= Any_class) and then not f.is_obsolete end feature -- Menu bars insert_global_menu_bar (text: TEXT_FORMATTER; d, l, h: BOOLEAN) -- Append a menu bar to `text'. deferred end insert_class_menu_bar (text: TEXT_FORMATTER; class_name: STRING_32) -- Append a menu bar to `text'. deferred end feature {NONE} -- Implementation type_of_group (a_group: CONF_GROUP): STRING_32 -- String representation of type of `a_group' require a_group_not_void: a_group /= Void do if a_group.is_library then Result := {STRING_32} "Library" elseif a_group.is_assembly or a_group.is_physical_assembly then Result := {STRING_32} "Assembly" else Result := {STRING_32} "Cluster" end ensure result_not_void: Result /= Void end note copyright: "Copyright (c) 1984-2020, Eiffel Software" license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)" licensing_options: "http://www.eiffel.com/licensing" copying: "[ This file is part of Eiffel Software's Eiffel Development Environment. Eiffel Software's Eiffel Development Environment is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License (available at the URL listed under "license" above). Eiffel Software's Eiffel Development Environment 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Eiffel Software's Eiffel Development Environment; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ]" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end