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
20 * Florian Brosch <flo.brosch@gmail.com>
24 using Valadoc
.Importer
;
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
;
52 public void add_package(Package package
) {
53 this
.packages
.add (package
);
56 public Vala
.CodeContext context
{
61 public Highlighter
.Highlighter highlighter
{
63 if (_highlighter
== null) {
64 _highlighter
= new Highlighter
.Highlighter ();
72 * The root of the wiki tree.
74 public WikiPageTree? wikitree
{
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
);
94 * Returns a list of all packages in the tree
96 * @return list of all packages
98 public Vala
.Collection
<Package
> get_package_list () {
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
) {
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
);
144 if (node
== null && element
.parent
!= null) {
145 node
= search_relative_to ((Node
) element
.parent
, path
);
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
);
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
);
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
);
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
);
212 private string[] split_name (string full_name
) {
213 string[] params
= (full_name
).split (".", -1);
214 int i
= 0; while (params
[i
] != null) i
++;
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
)) {
238 foreach (string dir
in Environment
.get_system_data_dirs ()) {
239 filename
= Path
.build_filename (dir
, basename
);
240 if (FileUtils
.test (filename
, FileTest
.EXISTS
)) {
248 public bool create_tree ( ) {
249 this
.add_dependencies_to_source_package ();
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
;
263 return _source_package
;
266 private void parse_wiki (DocumentationParser docparser
) {
267 this
.wikitree
= new
WikiPageTree ();
268 var pkg
= get_source_package ();
270 wikitree
.parse (settings
, docparser
, pkg
, reporter
);
274 private void check_wiki (DocumentationParser docparser
) {
275 Package pkg
= get_source_package ();
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
),
335 path
= Vala
.CodeContext
.realpath (path
);
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
);