Release 0.41.92
[vala-gnome.git] / libvaladoc / api / tree.vala
blobe357fe08e634336dee9bd113c5fc49ac21ce7d70
1 /* tree.vala
3 * Copyright (C) 2008-2011 Florian Brosch
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Florian Brosch <flo.brosch@gmail.com>
24 using Valadoc.Importer;
26 /**
27 * The root of the code tree.
29 public class Valadoc.Api.Tree {
30 private Vala.List<InheritDocContainer> inheritdocs = new Vala.ArrayList<InheritDocContainer> ();
31 private Vala.ArrayList<string> external_c_files = new Vala.ArrayList<string>(str_equal);
32 private Vala.ArrayList<Package> packages = new Vala.ArrayList<Package>();
33 private Package source_package = null;
34 private Settings settings;
35 private ErrorReporter reporter;
36 private Highlighter.Highlighter _highlighter;
37 private CTypeResolver _cresolver = null;
38 private Package _source_package;
41 private class InheritDocContainer {
42 public unowned Taglets.InheritDoc taglet;
43 public unowned Api.Node taglet_container;
45 public InheritDocContainer (Api.Node taglet_container, Taglets.InheritDoc taglet) {
46 this.taglet_container = taglet_container;
47 this.taglet = taglet;
52 public void add_package(Package package) {
53 this.packages.add (package);
56 public Vala.CodeContext context {
57 set;
58 get;
61 public Highlighter.Highlighter highlighter {
62 get {
63 if (_highlighter == null) {
64 _highlighter = new Highlighter.Highlighter ();
67 return _highlighter;
71 /**
72 * The root of the wiki tree.
74 public WikiPageTree? wikitree {
75 private set;
76 get;
79 /**
80 * Returns a list of C source files.
82 * @return list of C source files
84 public Vala.Collection<string> get_external_c_files () {
85 return external_c_files;
88 public void add_external_c_files (string name) {
89 external_c_files.add (name);
93 /**
94 * Returns a list of all packages in the tree
96 * @return list of all packages
98 public Vala.Collection<Package> get_package_list () {
99 return this.packages;
102 private void add_dependencies_to_source_package () {
103 if ( this.source_package != null ) {
104 Vala.ArrayList<Package> deplst = new Vala.ArrayList<Package> ();
105 foreach (Package pkg in this.packages) {
106 if (pkg != this.source_package) {
107 deplst.add (pkg);
110 this.source_package.set_dependency_list (deplst);
115 * Visits this node with the specified Visitor.
117 * @param visitor the visitor to be called while traversing
119 public void accept (Visitor visitor) {
120 visitor.visit_tree (this);
124 * Visits all children of this node with the given types with the specified Visitor.
126 * @param visitor the visitor to be called while traversing
128 public void accept_children (Visitor visitor) {
129 foreach (Node node in packages) {
130 node.accept (visitor);
134 private Node? search_relative_to (Node element, string[] path) {
135 Api.Node? node = element;
137 foreach (string name in path) {
138 node = node.find_by_name (name);
139 if (node == null) {
140 break;
144 if (node == null && element.parent != null) {
145 node = search_relative_to ((Node) element.parent, path);
148 return node;
151 public Node? search_symbol_path (Node? element, string[] path) {
152 Api.Node? node = null;
154 // relative to element
155 if (element != null) {
156 node = search_relative_to (element, path);
157 if (node != null) {
158 return node;
163 // absolute
164 foreach (Package package in packages) {
165 // search in root namespace
167 Node? global = package.find_by_name ("");
168 if (global != null) {
169 node = search_relative_to (global, path);
170 if (node != null) {
171 return node;
176 return null;
179 public TypeSymbol? search_symbol_type_cstr (string cname) {
180 if (_cresolver == null) {
181 _cresolver = new CTypeResolver (this);
184 return _cresolver.resolve_symbol_type (cname);
187 public Node? search_symbol_cstr (Node? element, string cname) {
188 if (_cresolver == null) {
189 _cresolver = new CTypeResolver (this);
192 return _cresolver.resolve_symbol (element, cname);
195 public Node? search_symbol_str (Node? element, string symname) {
196 string[] path = split_name (symname);
198 var node = search_symbol_path (element, path);
199 if (node != null) {
200 return node;
203 if (path.length >= 2 && path[path.length-2] == path[path.length-2]) {
204 path[path.length-2] = path[path.length-2]+"."+path[path.length-1];
205 path.resize (path.length-1);
206 return search_symbol_path (element, path);
209 return null;
212 private string[] split_name (string full_name) {
213 string[] params = (full_name).split (".", -1);
214 int i = 0; while (params[i] != null) i++;
215 params.length = i;
216 return params;
219 public Tree (ErrorReporter reporter, Settings settings, Vala.CodeContext context) {
220 this.settings = settings;
221 this.reporter = reporter;
222 this.context = context;
225 // copied from valacodecontext.vala
226 private string? get_file_path (string basename, string[] directories) {
227 string filename = null;
229 if (directories != null) {
230 foreach (string dir in directories) {
231 filename = Path.build_filename (dir, basename);
232 if (FileUtils.test (filename, FileTest.EXISTS)) {
233 return filename;
238 foreach (string dir in Environment.get_system_data_dirs ()) {
239 filename = Path.build_filename (dir, basename);
240 if (FileUtils.test (filename, FileTest.EXISTS)) {
241 return filename;
245 return null;
248 public bool create_tree ( ) {
249 this.add_dependencies_to_source_package ();
250 return true;
253 private Package? get_source_package () {
254 if (_source_package == null) {
255 foreach (Package pkg in packages) {
256 if (!pkg.is_package) {
257 _source_package = pkg;
258 break;
263 return _source_package;
266 private void parse_wiki (DocumentationParser docparser) {
267 this.wikitree = new WikiPageTree ();
268 var pkg = get_source_package ();
269 if (pkg != null) {
270 wikitree.parse (settings, docparser, pkg, reporter);
274 private void check_wiki (DocumentationParser docparser) {
275 Package pkg = get_source_package ();
276 if (pkg != null) {
277 wikitree.check (settings, docparser, pkg);
281 public void parse_comments (DocumentationParser docparser) {
282 parse_wiki (docparser);
284 foreach (Package pkg in this.packages) {
285 if (pkg.is_browsable (settings)) {
286 pkg.parse_comments (settings, docparser);
291 public void check_comments (DocumentationParser docparser) {
292 check_wiki (docparser);
294 foreach (Package pkg in this.packages) {
295 if (pkg.is_browsable (settings)) {
296 pkg.check_comments (settings, docparser);
297 postprocess_inheritdoc (docparser);
302 internal void register_inheritdoc (Api.Node container, Taglets.InheritDoc taglet) {
303 inheritdocs.add (new InheritDocContainer (container, taglet));
306 private void postprocess_inheritdoc (DocumentationParser docparser) {
307 while (!this.inheritdocs.is_empty) {
308 InheritDocContainer container = this.inheritdocs.remove_at (0);
310 docparser.transform_inheritdoc (container.taglet_container, container.taglet);
316 * Import documentation from various sources
318 * @param importers a list of importers
319 * @param packages sources
320 * @param import_directories List of directories where to find the files
322 public void import_comments (DocumentationImporter[] importers, string[] packages,
323 string[] import_directories)
325 Vala.HashSet<string> processed = new Vala.HashSet<string> ();
326 foreach (string pkg_name in packages) {
327 bool imported = false;
328 foreach (DocumentationImporter importer in importers) {
329 string? path = get_file_path ("%s.%s".printf (pkg_name, importer.file_extension),
330 import_directories);
331 if (path == null) {
332 continue;
335 path = Vala.CodeContext.realpath (path);
336 imported = true;
338 if (!processed.contains (path)) {
339 importer.process (path);
340 processed.add (path);
344 if (imported == false) {
345 reporter.simple_error (null, "'%s' not found in specified import directories", pkg_name);