From: Florian Brosch Date: Thu, 21 Jul 2011 01:16:59 +0000 (+0200) Subject: libvala: Move tree creation out into a plugin X-Git-Tag: 0.37.1~3^2~323 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=9801f58f964bd87d9e3763fad150e9055e3a08a1;p=thirdparty%2Fvala.git libvala: Move tree creation out into a plugin --- diff --git a/configure.in b/configure.in index d82394940..2612193b6 100755 --- a/configure.in +++ b/configure.in @@ -64,6 +64,8 @@ AC_CONFIG_FILES([Makefile icons/Makefile doc/Makefile src/libvaladoc/Makefile + src/driver/Makefile + src/driver/0.13.x/Makefile src/doclets/Makefile src/doclets/htm/Makefile src/doclets/devhelp/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index f9718b8ea..fcaf3a5a8 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ SUBDIRS = \ libvaladoc \ valadoc \ doclets \ + driver \ $(NULL) diff --git a/src/doclets/devhelp/Makefile.am b/src/doclets/devhelp/Makefile.am index 701fc17d8..af6aa5d0e 100755 --- a/src/doclets/devhelp/Makefile.am +++ b/src/doclets/devhelp/Makefile.am @@ -14,7 +14,7 @@ AM_CFLAGS = -g \ BUILT_SOURCES = libdoclet.vala.stamp -docletdir = $(libdir)/valadoc/plugins/devhelp +docletdir = $(libdir)/valadoc/doclets/devhelp libdoclet_la_LDFLAGS = -module -avoid-version -no-undefined diff --git a/src/doclets/gtkdoc/Makefile.am b/src/doclets/gtkdoc/Makefile.am index c985357ad..1f7e159be 100755 --- a/src/doclets/gtkdoc/Makefile.am +++ b/src/doclets/gtkdoc/Makefile.am @@ -14,7 +14,7 @@ AM_CFLAGS = -g \ BUILT_SOURCES = libdoclet.vala.stamp -docletdir = $(libdir)/valadoc/plugins/gtkdoc +docletdir = $(libdir)/valadoc/doclets/gtkdoc libdoclet_la_LDFLAGS = -module -avoid-version -no-undefined diff --git a/src/doclets/htm/Makefile.am b/src/doclets/htm/Makefile.am index 12612a246..5af5092db 100755 --- a/src/doclets/htm/Makefile.am +++ b/src/doclets/htm/Makefile.am @@ -14,7 +14,7 @@ AM_CFLAGS = -g \ BUILT_SOURCES = libdoclet.vala.stamp -docletdir = $(libdir)/valadoc/plugins/html +docletdir = $(libdir)/valadoc/doclets/html libdoclet_la_LDFLAGS = -module -avoid-version -no-undefined diff --git a/src/driver/0.13.x/Makefile.am b/src/driver/0.13.x/Makefile.am new file mode 100755 index 000000000..986dd79b9 --- /dev/null +++ b/src/driver/0.13.x/Makefile.am @@ -0,0 +1,62 @@ +NULL = + + +AM_CFLAGS = -g \ + -DPACKAGE_ICONDIR=\"$(datadir)/valadoc/icons/\" \ + -I ../../libvaladoc/ \ + $(GLIB_CFLAGS) \ + $(LIBGEE_CFLAGS) \ + $(LIBVALA_CFLAGS) \ + $(NULL) + + + +BUILT_SOURCES = libdriver.vala.stamp + + +docletdir = $(libdir)/valadoc/drivers/0.13.x + + +libdriver_la_LDFLAGS = -module -avoid-version -no-undefined + + +doclet_LTLIBRARIES = \ + libdriver.la \ + $(NULL) + + +libdriver_la_VALASOURCES = \ + initializerbuilder.vala \ + symbolresolver.vala \ + treebuilder.vala \ + driver.vala \ + $(NULL) + + +libdriver_la_SOURCES = \ + libdriver.vala.stamp \ + $(libdriver_la_VALASOURCES:.vala=.c) \ + $(NULL) + + +libdriver.vala.stamp: $(libdriver_la_VALASOURCES) + $(VALAC) -C --vapidir $(top_srcdir)/src/vapi --vapidir $(top_srcdir)/src/libvaladoc --pkg $(VALA_PACKAGE) --pkg gee-1.0 --pkg valadoc-1.0 --basedir . $^ + touch $@ + + +libdriver_la_LIBADD = \ + ../../libvaladoc/libvaladoc.la \ + $(GLIB_LIBS) \ + $(LIBVALA_LIBS) \ + $(LIBGEE_LIBS) \ + $(NULL) + + +EXTRA_DIST = $(libdriver_la_VALASOURCES) libdriver.vala.stamp + + +MAINTAINERCLEANFILES = \ + $(libdriver_la_VALASOURCES:.vala=.c) \ + $(NULL) + + diff --git a/src/driver/0.13.x/driver.vala b/src/driver/0.13.x/driver.vala new file mode 100755 index 000000000..d5e8e7273 --- /dev/null +++ b/src/driver/0.13.x/driver.vala @@ -0,0 +1,52 @@ +/* driver.vala + * + * Copyright (C) 2011 Florian Brosch + * + * 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: + * Florian Brosch + */ + +using Valadoc.Api; +using Gee; + + + +/** + * Creates an simpler, minimized, more abstract AST for valacs AST. + */ +public class Valadoc.Drivers.Driver : Object, Valadoc.Driver { + + public Api.Tree? build (Settings settings, ErrorReporter reporter) { + TreeBuilder builder = new TreeBuilder (); + Api.Tree? tree = builder.build (settings, reporter); + if (reporter.errors > 0) { + return null; + } + + SymbolResolver resolver = new SymbolResolver (builder); + tree.accept (resolver); + + return tree; + } +} + + +[ModuleInit] +public Type register_plugin (GLib.TypeModule module) { + return typeof (Valadoc.Drivers.Driver); +} + diff --git a/src/libvaladoc/api/initializerbuilder.vala b/src/driver/0.13.x/initializerbuilder.vala similarity index 99% rename from src/libvaladoc/api/initializerbuilder.vala rename to src/driver/0.13.x/initializerbuilder.vala index 3f580e178..70fd1d6bb 100644 --- a/src/libvaladoc/api/initializerbuilder.vala +++ b/src/driver/0.13.x/initializerbuilder.vala @@ -509,11 +509,9 @@ private class Valadoc.Api.InitializerBuilder : Vala.CodeVisitor { first = false; } - var run = new Run (Run.Style.ITALIC); - run.content.add (new Text (" [...] ")); signature.append (") => {", false); - signature.append_content (run, false); + signature.append_highlighted (" [...] ", false); signature.append ("}", false); } diff --git a/src/libvaladoc/api/symbolresolver.vala b/src/driver/0.13.x/symbolresolver.vala similarity index 90% rename from src/libvaladoc/api/symbolresolver.vala rename to src/driver/0.13.x/symbolresolver.vala index 39d5a77b3..f227cd0b1 100644 --- a/src/libvaladoc/api/symbolresolver.vala +++ b/src/driver/0.13.x/symbolresolver.vala @@ -20,31 +20,32 @@ * Florian Brosch */ +using Valadoc.Api; using Gee; -public class Valadoc.Api.SymbolResolver : Visitor { +public class Valadoc.Drivers.SymbolResolver : Visitor { private HashMap symbol_map; private Valadoc.Api.Class glib_error; - private Tree root; + private Api.Tree root; - public SymbolResolver (HashMap symbol_map, Valadoc.Api.Class glib_error) { - this.symbol_map = symbol_map; - this.glib_error = glib_error; + public SymbolResolver (TreeBuilder builder) { + this.symbol_map = builder.get_symbol_map (); + this.glib_error = builder.get_glib_error (); } private Symbol? resolve (Vala.Symbol symbol) { return symbol_map.get (symbol); } - private void resolve_array_type_references (Array ptr) { + private void resolve_array_type_references (Api.Array ptr) { Api.Item data_type = ptr.data_type; if (data_type == null) { // void - } else if (data_type is Array) { - resolve_array_type_references ((Array) data_type); + } else if (data_type is Api.Array) { + resolve_array_type_references ((Api.Array) data_type); } else if (data_type is Pointer) { - resolve_pointer_type_references ((Pointer) data_type); + resolve_pointer_type_references ((Api.Pointer) data_type); } else { resolve_type_reference ((TypeReference) data_type); } @@ -54,8 +55,8 @@ public class Valadoc.Api.SymbolResolver : Visitor { Api.Item type = ptr.data_type; if (type == null) { // void - } else if (type is Array) { - resolve_array_type_references ((Array) type); + } else if (type is Api.Array) { + resolve_array_type_references ((Api.Array) type); } else if (type is Pointer) { resolve_pointer_type_references ((Pointer) type); } else { @@ -87,15 +88,15 @@ public class Valadoc.Api.SymbolResolver : Visitor { if (reference.data_type is Pointer) { resolve_pointer_type_references ((Pointer)reference.data_type); - } else if (reference.data_type is Array) { - resolve_array_type_references ((Array)reference.data_type); + } else if (reference.data_type is Api.Array) { + resolve_array_type_references ((Api.Array)reference.data_type); } } /** * {@inheritDoc} */ - public override void visit_tree (Tree item) { + public override void visit_tree (Api.Tree item) { this.root = item; item.accept_children (this); this.root = null; @@ -217,7 +218,7 @@ public class Valadoc.Api.SymbolResolver : Visitor { /** * {@inheritDoc} */ - public override void visit_signal (Signal item) { + public override void visit_signal (Api.Signal item) { resolve_type_reference (item.return_type); item.accept_all_children (this, false); @@ -296,7 +297,7 @@ public class Valadoc.Api.SymbolResolver : Visitor { /** * {@inheritDoc} */ - public override void visit_enum_value (EnumValue item) { + public override void visit_enum_value (Api.EnumValue item) { if (((Vala.EnumValue) item.data).value != null) { SignatureBuilder signature = new SignatureBuilder (); @@ -308,3 +309,6 @@ public class Valadoc.Api.SymbolResolver : Visitor { item.accept_all_children (this, false); } } + + + diff --git a/src/driver/0.13.x/treebuilder.vala b/src/driver/0.13.x/treebuilder.vala new file mode 100644 index 000000000..a4a05ec9b --- /dev/null +++ b/src/driver/0.13.x/treebuilder.vala @@ -0,0 +1,988 @@ +/* treebuilder.vala + * + * Copyright (C) 2011 Florian Brosch + * + * 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: + * Florian Brosch + */ + + +using Valadoc.Api; +using Gee; + + +/** + * Creates an simpler, minimized, more abstract AST for valacs AST. + */ +public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { + private ArrayList packages = new ArrayList (); + private PackageMetaData source_package; + + private HashMap files = new HashMap (); + private HashMap symbol_map = new HashMap (); + + private ErrorReporter reporter; + private Settings settings; + + private Api.Node current_node; + private Api.Tree tree; + + private Valadoc.Api.Class glib_error = null; + + + // + // Accessors + // + + public Api.Class get_glib_error () { + return glib_error; + } + + public HashMap get_symbol_map () { + return symbol_map; + } + + + // + // + // + + private class PackageMetaData { + public Package package; + public HashMap namespaces = new HashMap (); + public ArrayList files = new ArrayList (); + + public PackageMetaData (Package package) { + this.package = package; + } + + public Namespace get_namespace (Vala.Namespace vns, SourceFile? file) { + Namespace? ns = namespaces.get (vns); + if (ns != null) { + return ns; + } + + // find documentation comment if existing: + SourceComment? comment = null; + if (vns.source_reference != null) { + foreach (Vala.Comment c in vns.get_comments()) { + if (c.source_reference.file == vns.source_reference.file) { + Vala.SourceReference pos = c.source_reference; + comment = new SourceComment (c.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column); + break; + } + } + } + + // find parent if existing + var parent_vns = vns.parent_symbol; + + if (parent_vns == null) { + ns = new Namespace (package, file, vns.name, comment, vns); + package.add_child (ns); + } else { + Namespace parent_ns = get_namespace ((Vala.Namespace) parent_vns, file); + ns = new Namespace (parent_ns, file, vns.name, comment, vns); + parent_ns.add_child (ns); + } + + namespaces.set (vns, ns); + return ns; + } + + public void register_source_file (Vala.SourceFile file) { + files.add (file); + } + + public bool is_package_for_file (Vala.SourceFile source_file) { + if (source_file.file_type == Vala.SourceFileType.SOURCE && !package.is_package) { + return true; + } + + return files.contains (source_file); + } + } + + + // + // Type constructor translation helpers: + // + + private Pointer create_pointer (Vala.PointerType vtyperef, Item parent) { + Pointer ptr = new Pointer (parent, vtyperef); + + Vala.DataType vntype = vtyperef.base_type; + if (vntype is Vala.PointerType) { + ptr.data_type = create_pointer ((Vala.PointerType) vntype, ptr); + } else if (vntype is Vala.ArrayType) { + ptr.data_type = create_array ((Vala.ArrayType) vntype, ptr); + } else { + ptr.data_type = create_type_reference (vntype, ptr); + } + + return ptr; + } + + private Api.Array create_array (Vala.ArrayType vtyperef, Item parent) { + Api.Array arr = new Api.Array (parent, vtyperef); + + Vala.DataType vntype = vtyperef.element_type; + if (vntype is Vala.ArrayType) { + arr.data_type = create_array ((Vala.ArrayType) vntype, arr); + } else { + arr.data_type = create_type_reference (vntype, arr); + } + + return arr; + } + + private TypeReference create_type_reference (Vala.DataType? vtyperef, Item parent) { + bool is_nullable = vtyperef != null && vtyperef.nullable && !(vtyperef is Vala.GenericType) && !(vtyperef is Vala.PointerType); + string? signature = (vtyperef != null && vtyperef.data_type != null)? Vala.GVariantModule.get_dbus_signature (vtyperef.data_type) : null; + bool pass_ownership = type_reference_pass_ownership (vtyperef); + Ownership ownership = get_type_reference_ownership (vtyperef); + bool is_dynamic = vtyperef != null && vtyperef.is_dynamic; + + TypeReference type_ref = new TypeReference (parent, ownership, pass_ownership, is_dynamic, is_nullable, signature, vtyperef); + + if (vtyperef is Vala.PointerType) { + type_ref.data_type = create_pointer ((Vala.PointerType) vtyperef, type_ref); + } else if (vtyperef is Vala.ArrayType) { + type_ref.data_type = create_array ((Vala.ArrayType) vtyperef, type_ref); + } + + // type parameters: + if (vtyperef != null) { + foreach (Vala.DataType vdtype in vtyperef.get_type_arguments ()) { + var type_param = create_type_reference (vdtype, type_ref); + type_ref.add_type_argument (type_param); + } + } + + return type_ref; + } + + + + // + // Translation helpers: + // + + private SourceComment? create_comment (Vala.Comment? comment) { + if (comment != null) { + Vala.SourceReference pos = comment.source_reference; + SourceFile file = files.get (pos.file); + return new SourceComment (comment.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column); + } + + return null; + } + + private string get_method_name (Vala.Method element) { + if (element is Vala.CreationMethod) { + if (element.name == ".new") { + return element.parent_symbol.name; + } else { + return element.parent_symbol.name + "." + element.name; + } + } + + return element.name; + } + + private PackageMetaData? get_package_meta_data (Package pkg) { + foreach (PackageMetaData data in packages) { + if (data.package == pkg) { + return data; + } + } + + return null; + } + + private PackageMetaData register_package (Package package) { + PackageMetaData meta_data = new PackageMetaData (package); + tree.add_package (package); + packages.add (meta_data); + return meta_data; + } + + private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) { + SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ()); + files.set (source_file, file); + + meta_data.register_source_file (source_file); + return file; + } + + private SourceFile? get_source_file (Vala.Symbol symbol) { + Vala.SourceReference source_ref = symbol.source_reference; + if (source_ref == null) { + return null; + } + + SourceFile file = files.get (source_ref.file); + assert (file != null); + return file; + } + + private Package? find_package_for_file (Vala.SourceFile source_file) { + foreach (PackageMetaData pkg in this.packages) { + if (pkg.is_package_for_file (source_file)) { + return pkg.package; + } + } + + return null; + } + + + private Namespace get_namespace (Package pkg, Vala.Symbol symbol, SourceFile? file) { + // Find the closest namespace in our vala-tree + Vala.Symbol namespace_symbol = symbol; + while (!(namespace_symbol is Vala.Namespace)) { + namespace_symbol = namespace_symbol.parent_symbol; + } + + PackageMetaData? meta_data = get_package_meta_data (pkg); + assert (meta_data != null); + + return meta_data.get_namespace ((Vala.Namespace) namespace_symbol, file); + } + + private MethodBindingType get_method_binding_type (Vala.Method element) { + if (element.is_inline) { + return MethodBindingType.INLINE; + } else if (element.is_abstract) { + return MethodBindingType.ABSTRACT; + } else if (element.is_virtual) { + return MethodBindingType.VIRTUAL; + } else if (element.overrides) { + return MethodBindingType.OVERRIDE; + } else if (element.is_inline) { + return MethodBindingType.INLINE; + } else if (element.binding == Vala.MemberBinding.INSTANCE) { + return MethodBindingType.STATIC; + } + return MethodBindingType.UNMODIFIED; + } + + + private SymbolAccessibility get_access_modifier(Vala.Symbol symbol) { + switch (symbol.access) { + case Vala.SymbolAccessibility.PROTECTED: + return SymbolAccessibility.PROTECTED; + + case Vala.SymbolAccessibility.INTERNAL: + return SymbolAccessibility.INTERNAL; + + case Vala.SymbolAccessibility.PRIVATE: + return SymbolAccessibility.PRIVATE; + + case Vala.SymbolAccessibility.PUBLIC: + return SymbolAccessibility.PUBLIC; + + default: + error ("Unknown symbol accessibility modifier found"); + } + } + + private PropertyAccessorType get_property_accessor_type (Vala.PropertyAccessor element) { + if (element.construction) { + return PropertyAccessorType.CONSTRUCT; + } else if (element.writable) { + return PropertyAccessorType.SET; + } else if (element.readable) { + return PropertyAccessorType.GET; + } + + error ("Unknown symbol accessibility type"); + } + + private bool type_reference_pass_ownership (Vala.DataType? element) { + if (element == null) { + return false; + } + + Vala.CodeNode? node = element.parent_node; + if (node == null) { + return false; + } + if (node is Vala.Parameter) { + return (((Vala.Parameter)node).direction == Vala.ParameterDirection.IN && + ((Vala.Parameter)node).variable_type.value_owned); + } + if (node is Vala.Property) { + return ((Vala.Property)node).property_type.value_owned; + } + + return false; + } + + private bool is_type_reference_unowned (Vala.DataType? element) { + if (element == null) { + return false; + } + + // non ref counted types are weak, not unowned + if (element.data_type is Vala.TypeSymbol && ((Vala.TypeSymbol) element.data_type).is_reference_counting () == true) { + return false; + } + + // FormalParameters are weak by default + return (element.parent_node is Vala.Parameter == false)? element.is_weak () : false; + } + + private bool is_type_reference_owned (Vala.DataType? element) { + if (element == null) { + return false; + } + + Vala.CodeNode parent = element.parent_node; + + // parameter: + if (parent is Vala.Parameter) { + if (((Vala.Parameter)parent).direction != Vala.ParameterDirection.IN) { + return false; + } + return ((Vala.Parameter)parent).variable_type.value_owned; + } + + return false; + } + + private bool is_type_reference_weak (Vala.DataType? element) { + if (element == null) { + return false; + } + + // non ref counted types are unowned, not weak + if (element.data_type is Vala.TypeSymbol && ((Vala.TypeSymbol) element.data_type).is_reference_counting () == false) { + return false; + } + + // FormalParameters are weak by default + return (element.parent_node is Vala.Parameter == false)? element.is_weak () : false; + } + + private Ownership get_type_reference_ownership (Vala.DataType? element) { + if (is_type_reference_owned (element)) { + return Ownership.OWNED; + } else if (is_type_reference_weak (element)) { + return Ownership.WEAK; + } else if (is_type_reference_unowned (element)) { + return Ownership.UNOWNED; + } + + return Ownership.DEFAULT; + } + + private Ownership get_property_ownership (Vala.PropertyAccessor element) { + if (element.value_type.value_owned) { + return Ownership.OWNED; + } + + // the exact type (weak, unowned) does not matter + return Ownership.UNOWNED; + } + + private PropertyBindingType get_property_binding_type (Vala.Property element) { + if (element.is_abstract) { + return PropertyBindingType.ABSTRACT; + } else if (element.is_virtual) { + return PropertyBindingType.VIRTUAL; + } else if (element.overrides) { + return PropertyBindingType.OVERRIDE; + } + + return PropertyBindingType.UNMODIFIED; + } + + private FormalParameterType get_formal_parameter_type (Vala.Parameter element) { + if (element.direction == Vala.ParameterDirection.OUT) { + return FormalParameterType.OUT; + } else if (element.direction == Vala.ParameterDirection.REF) { + return FormalParameterType.REF; + } else if (element.direction == Vala.ParameterDirection.IN) { + return FormalParameterType.IN; + } + + error ("Unknown formal parameter type"); + } + + + // + // Vala tree creation: + // + + private bool add_package (Vala.CodeContext context, string pkg) { + if (context.has_package (pkg)) { + // ignore multiple occurences of the same package + return true; + } + + var package_path = context.get_vapi_path (pkg) ?? context.get_gir_path (pkg); + if (package_path == null) { + Vala.Report.error (null, "Package `%s' not found in specified Vala API directories or GObject-Introspection GIR directories".printf (pkg)); + return false; + } + + context.add_package (pkg); + + var vfile = new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, package_path); + context.add_source_file (vfile); + Package vdpkg = new Package (vfile, pkg, true, null); + register_source_file (register_package (vdpkg), vfile); + + add_deps (context, Path.build_filename (Path.get_dirname (package_path), "%s.deps".printf (pkg)), pkg); + return true; + } + + private void add_deps (Vala.CodeContext context, string file_path, string pkg_name) { + if (FileUtils.test (file_path, FileTest.EXISTS)) { + try { + string deps_content; + ulong deps_len; + FileUtils.get_contents (file_path, out deps_content, out deps_len); + foreach (string dep in deps_content.split ("\n")) { + dep.strip (); + if (dep != "") { + if (!add_package (context, dep)) { + Vala.Report.error (null, "%s, dependency of %s, not found in specified Vala API directories".printf (dep, pkg_name)); + } + } + } + } catch (FileError e) { + Vala.Report.error (null, "Unable to read dependency file: %s".printf (e.message)); + } + } + } + + /** + * Adds the specified packages to the list of used packages. + * + * @param context The code context + * @param packages a list of package names + */ + private void add_depencies (Vala.CodeContext context, string[] packages) { + foreach (string package in packages) { + if (!add_package (context, package)) { + Vala.Report.error (null, "Package `%s' not found in specified Vala API directories or GObject-Introspection GIR directories".printf (package)); + } + } + } + + /** + * Add the specified source file to the context. Only .vala, .vapi, .gs, + * and .c files are supported. + */ + private void add_documented_files (Vala.CodeContext context, string[] sources) { + if (sources == null) { + return; + } + + foreach (string source in sources) { + if (FileUtils.test (source, FileTest.EXISTS)) { + var rpath = realpath (source); + if (source.has_suffix (".vala") || source.has_suffix (".gs")) { + var source_file = new Vala.SourceFile (context, Vala.SourceFileType.SOURCE, rpath); + + if (source_package == null) { + source_package = register_package (new Package (source_file, settings.pkg_name, false, null)); + } + + register_source_file (source_package, source_file); + + if (context.profile == Vala.Profile.POSIX) { + // import the Posix namespace by default (namespace of backend-specific standard library) + var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "Posix", null)); + source_file.add_using_directive (ns_ref); + context.root.add_using_directive (ns_ref); + } else if (context.profile == Vala.Profile.GOBJECT) { + // import the GLib namespace by default (namespace of backend-specific standard library) + var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null)); + source_file.add_using_directive (ns_ref); + context.root.add_using_directive (ns_ref); + } + + context.add_source_file (source_file); + } else if (source.has_suffix (".vapi")) { + string file_name = Path.get_basename (source); + file_name = file_name.substring (0, file_name.length - ".vapi".length); + + var vfile = new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, rpath); + Package vdpkg = new Package (vfile, file_name, true, null); + context.add_source_file (vfile); + + register_source_file (register_package (vdpkg), vfile); + + add_deps (context, Path.build_filename (Path.get_dirname (source), "%s.deps".printf (file_name)), file_name); + } else if (source.has_suffix (".c")) { + context.add_c_source_file (rpath); + tree.add_external_c_files (rpath); + } else { + Vala.Report.error (null, "%s is not a supported source file type. Only .vala, .vapi, .gs, and .c files are supported.".printf (source)); + } + } else { + Vala.Report.error (null, "%s not found".printf (source)); + } + } + } + + private Vala.CodeContext create_valac_tree (Settings settings) { + // init context: + var context = new Vala.CodeContext (); + Vala.CodeContext.push (context); + + + // settings: + context.experimental = settings.experimental; + context.experimental_non_null = settings.experimental || settings.experimental_non_null; + context.vapi_directories = settings.vapi_directories; + context.report.enable_warnings = settings.verbose; + + if (settings.basedir == null) { + context.basedir = realpath ("."); + } else { + context.basedir = realpath (settings.basedir); + } + + if (settings.directory != null) { + context.directory = realpath (settings.directory); + } else { + context.directory = context.basedir; + } + + + // add default packages: + if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) { + context.profile = Vala.Profile.GOBJECT; + context.add_define ("GOBJECT"); + } + + + if (settings.defines != null) { + foreach (string define in settings.defines) { + context.add_define (define); + } + } + + if (context.profile == Vala.Profile.POSIX) { + // default package + if (!add_package (context, "posix")) { + Vala.Report.error (null, "posix not found in specified Vala API directories"); + } + } else if (context.profile == Vala.Profile.GOBJECT) { + int glib_major = 2; + int glib_minor = 12; + + context.target_glib_major = glib_major; + context.target_glib_minor = glib_minor; + if (context.target_glib_major != 2) { + Vala.Report.error (null, "This version of valac only supports GLib 2"); + } + + // default packages + if (!this.add_package (context, "glib-2.0")) { // + Vala.Report.error (null, "glib-2.0 not found in specified Vala API directories"); + } + + if (!this.add_package (context, "gobject-2.0")) { // + Vala.Report.error (null, "gobject-2.0 not found in specified Vala API directories"); + } + } + + + // add user defined files: + add_depencies (context, settings.packages); + if (reporter.errors > 0) { + return context; + } + + add_documented_files (context, settings.source_files); + if (reporter.errors > 0) { + return context; + } + + + // parse vala-code: + Vala.Parser parser = new Vala.Parser (); + + parser.parse (context); + if (context.report.get_errors () > 0) { + return context; + } + + + // check context: + context.check (); + if (context.report.get_errors () > 0) { + return context; + } + + return context; + } + + + + // + // Valadoc tree creation: + // + + private void process_children (Api.Node node, Vala.Symbol element) { + Api.Node old_node = current_node; + current_node = node; + element.accept_children (this); + current_node = old_node; + } + + private Api.Node get_parent_node_for (Vala.Symbol element) { + if (current_node != null) { + return current_node; + } + + Vala.SourceFile vala_source_file = element.source_reference.file; + Package package = find_package_for_file (vala_source_file); + SourceFile? source_file = get_source_file (element); + + return get_namespace (package, element, source_file); + } + + /** + * {@inheritDoc} + */ + public override void visit_namespace (Vala.Namespace element) { + element.accept_children (this); + } + + /** + * {@inheritDoc} + */ + public override void visit_class (Vala.Class element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + bool is_basic_type = element.base_class == null && element.name == "string"; + + Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name (element), element.get_param_spec_function (), element.get_type_id (), element.get_ref_function (), element.get_unref_function (), element.get_take_value_function (), element.get_get_value_function (), element.get_set_value_function (), element.is_fundamental (), element.is_abstract, is_basic_type, element); + symbol_map.set (element, node); + parent.add_child (node); + + // relations + foreach (Vala.DataType vala_type_ref in element.get_base_types ()) { + var type_ref = create_type_reference (vala_type_ref, node); + + if (vala_type_ref.data_type is Vala.Interface) { + node.add_interface (type_ref); + } else { + node.base_type = type_ref; + } + } + + process_children (node, element); + + // save GLib.Error + if (glib_error == null && node.get_full_name () == "GLib.Error") { + glib_error = node; + } + } + + /** + * {@inheritDoc} + */ + public override void visit_interface (Vala.Interface element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Interface node = new Interface (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name (element), element); + symbol_map.set (element, node); + parent.add_child (node); + + // prerequisites: + foreach (Vala.DataType vala_type_ref in element.get_prerequisites ()) { + TypeReference type_ref = create_type_reference (vala_type_ref, node); + if (vala_type_ref.data_type is Vala.Interface) { + node.add_interface (type_ref); + } else { + node.base_type = type_ref; + } + } + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_struct (Vala.Struct element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + bool is_basic_type = element.base_type == null && (element.is_boolean_type () || element.is_floating_type () || element.is_integer_type ()); + + Struct node = new Struct (parent, file, element.name, get_access_modifier(element), comment, element.get_cname(), element.get_dup_function (), element.get_free_function (), is_basic_type, element); + symbol_map.set (element, node); + parent.add_child (node); + + // parent type: + Vala.ValueType? basetype = element.base_type as Vala.ValueType; + if (basetype != null) { + node.base_type = create_type_reference (basetype, node); + } + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_field (Vala.Field element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Field node = new Field (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element.binding == Vala.MemberBinding.STATIC, element.is_volatile, element); + node.field_type = create_type_reference (element.variable_type, node); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_property (Vala.Property element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Property node = new Property (parent, file, element.name, get_access_modifier(element), comment, element.nick, Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.is_dbus_visible (element), get_property_binding_type (element), element); + node.property_type = create_type_reference (element.property_type, node); + symbol_map.set (element, node); + parent.add_child (node); + + // Process property type + if (element.get_accessor != null) { + var accessor = element.get_accessor; + node.getter = new PropertyAccessor (node, file, element.name, get_access_modifier(element), accessor.get_cname(), get_property_accessor_type (accessor), get_property_ownership (accessor), accessor); + } + + if (element.set_accessor != null) { + var accessor = element.set_accessor; + node.setter = new PropertyAccessor (node, file, element.name, get_access_modifier(element), accessor.get_cname(), get_property_accessor_type (accessor), get_property_ownership (accessor), accessor); + } + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_creation_method (Vala.CreationMethod element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Method node = new Method (parent, file, get_method_name (element), get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.dbus_result_name (element), (element.coroutine)? element.get_finish_cname () : null, get_method_binding_type (element), element.coroutine, Vala.GDBusServerModule.is_dbus_visible (element), element is Vala.CreationMethod, element); + node.return_type = create_type_reference (element.return_type, node); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_method (Vala.Method element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Method node = new Method (parent, file, get_method_name (element), get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.dbus_result_name (element), (element.coroutine)? element.get_finish_cname () : null, get_method_binding_type (element), element.coroutine, Vala.GDBusServerModule.is_dbus_visible (element), element is Vala.CreationMethod, element); + node.return_type = create_type_reference (element.return_type, node); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_signal (Vala.Signal element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Api.Signal node = new Api.Signal (parent, file, element.name, get_access_modifier(element), comment, element.get_cname(), Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.is_dbus_visible (element), element.is_virtual, element); + node.return_type = create_type_reference (element.return_type, node); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_delegate (Vala.Delegate element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Delegate node = new Delegate (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element.has_target, element); + node.return_type = create_type_reference (element.return_type, node); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_enum (Vala.Enum element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Symbol node = new Enum (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_enum_value (Vala.EnumValue element) { + Api.Enum parent = (Enum) get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Symbol node = new Api.EnumValue (parent, file, element.name, comment, element.get_cname (), element); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_constant (Vala.Constant element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Constant node = new Constant (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element); + node.constant_type = create_type_reference (element.type_reference, node); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_error_domain (Vala.ErrorDomain element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Symbol node = new ErrorDomain (parent, file, element.name, get_access_modifier(element), comment, element.get_cname(), Vala.GDBusModule.get_dbus_name (element), element); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_error_code (Vala.ErrorCode element) { + Api.ErrorDomain parent = (ErrorDomain) get_parent_node_for (element); + SourceFile? file = get_source_file (element); + SourceComment? comment = create_comment (element.comment); + + Symbol node = new Api.ErrorCode (parent, file, element.name, comment, element.get_cname (), Vala.GDBusModule.get_dbus_name_for_member (element), element); + symbol_map.set (element, node); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_type_parameter (Vala.TypeParameter element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + + Symbol node = new TypeParameter (parent, file, element.name, element); + parent.add_child (node); + + process_children (node, element); + } + + /** + * {@inheritDoc} + */ + public override void visit_formal_parameter (Vala.Parameter element) { + Api.Node parent = get_parent_node_for (element); + SourceFile? file = get_source_file (element); + + FormalParameter node = new FormalParameter (parent, file, element.name, get_access_modifier(element), get_formal_parameter_type (element), element.ellipsis, element); + node.parameter_type = create_type_reference (element.variable_type, node); + parent.add_child (node); + + process_children (node, element); + } + + + // + // startpoint: + // + + public Api.Tree? build (Settings settings, ErrorReporter reporter) { + this.tree = new Api.Tree (reporter, settings); + this.settings = settings; + this.reporter = reporter; + + var context = create_valac_tree (settings); + + reporter.warnings_offset = context.report.get_warnings (); + reporter.errors_offset = context.report.get_errors (); + + if (context == null) { + return null; + } + + context.accept(this); + + return (reporter.errors == 0)? tree : null; + } +} + + diff --git a/src/driver/Makefile.am b/src/driver/Makefile.am new file mode 100755 index 000000000..5e22e8878 --- /dev/null +++ b/src/driver/Makefile.am @@ -0,0 +1,10 @@ +# src/Makefile.am + +NULL = + + +SUBDIRS = \ + 0.13.x \ + $(NULL) + + diff --git a/src/libvaladoc/Makefile.am b/src/libvaladoc/Makefile.am index da6bf1946..64c277bca 100755 --- a/src/libvaladoc/Makefile.am +++ b/src/libvaladoc/Makefile.am @@ -43,7 +43,6 @@ libvaladoc_la_VALASOURCES = \ importer/valadocdocumentationimporter.vala \ importer/valadocdocumentationimporterscanner.vala \ api/symbolaccessibility.vala \ - api/symbolresolver.vala \ api/sourcecomment.vala \ api/array.vala \ api/class.vala \ @@ -57,7 +56,6 @@ libvaladoc_la_VALASOURCES = \ api/formalparameter.vala \ api/formalparametertype.vala \ api/interface.vala \ - api/initializerbuilder.vala \ api/item.vala \ api/member.vala \ api/method.vala \ diff --git a/src/libvaladoc/api/class.vala b/src/libvaladoc/api/class.vala index 00441d638..a820d8286 100755 --- a/src/libvaladoc/api/class.vala +++ b/src/libvaladoc/api/class.vala @@ -226,11 +226,11 @@ public class Valadoc.Api.Class : TypeSymbol { return _known_derived_interfaces.read_only_view; } - internal void register_derived_interface (Interface iface) { + public void register_derived_interface (Interface iface) { _known_derived_interfaces.add (iface); } - internal void register_child_class (Class cl) { + public void register_child_class (Class cl) { if (this.base_type != null) { ((Class) this.base_type.data_type).register_child_class (cl); } diff --git a/src/libvaladoc/api/driver.vala b/src/libvaladoc/api/driver.vala index c1376b176..0bcfc63e5 100755 --- a/src/libvaladoc/api/driver.vala +++ b/src/libvaladoc/api/driver.vala @@ -25,953 +25,18 @@ using Gee; /** - * Creates an simpler, minimized, more abstract AST for valacs AST. + * A plugin register function for drivers + * + * @see ModuleLoader */ -public class Valadoc.Api.Driver : Vala.CodeVisitor { - private ArrayList packages = new ArrayList (); - private PackageMetaData source_package; - - private HashMap files = new HashMap (); - private HashMap symbol_map = new HashMap (); - - private ErrorReporter reporter; - private Settings settings; - - private Api.Node current_node; - private Api.Tree tree; - - private Valadoc.Api.Class glib_error = null; - - - private class PackageMetaData { - public Package package; - public HashMap namespaces = new HashMap (); - public ArrayList files = new ArrayList (); - - public PackageMetaData (Package package) { - this.package = package; - } - - public Namespace get_namespace (Vala.Namespace vns, SourceFile? file) { - Namespace? ns = namespaces.get (vns); - if (ns != null) { - return ns; - } - - // find documentation comment if existing: - SourceComment? comment = null; - if (vns.source_reference != null) { - foreach (Vala.Comment c in vns.get_comments()) { - if (c.source_reference.file == vns.source_reference.file) { - Vala.SourceReference pos = c.source_reference; - comment = new SourceComment (c.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column); - break; - } - } - } - - // find parent if existing - var parent_vns = vns.parent_symbol; - - if (parent_vns == null) { - ns = new Namespace (package, file, vns.name, comment, vns); - package.add_child (ns); - } else { - Namespace parent_ns = get_namespace ((Vala.Namespace) parent_vns, file); - ns = new Namespace (parent_ns, file, vns.name, comment, vns); - parent_ns.add_child (ns); - } - - namespaces.set (vns, ns); - return ns; - } - - public void register_source_file (Vala.SourceFile file) { - files.add (file); - } - - public bool is_package_for_file (Vala.SourceFile source_file) { - if (source_file.file_type == Vala.SourceFileType.SOURCE && !package.is_package) { - return true; - } - - return files.contains (source_file); - } - } - - - // - // Type constructor translation helpers: - // - - private Pointer create_pointer (Vala.PointerType vtyperef, Item parent) { - Pointer ptr = new Pointer (parent, vtyperef); - - Vala.DataType vntype = vtyperef.base_type; - if (vntype is Vala.PointerType) { - ptr.data_type = create_pointer ((Vala.PointerType) vntype, ptr); - } else if (vntype is Vala.ArrayType) { - ptr.data_type = create_array ((Vala.ArrayType) vntype, ptr); - } else { - ptr.data_type = create_type_reference (vntype, ptr); - } - - return ptr; - } - - private Array create_array (Vala.ArrayType vtyperef, Item parent) { - Array arr = new Array (parent, vtyperef); - - Vala.DataType vntype = vtyperef.element_type; - if (vntype is Vala.ArrayType) { - arr.data_type = create_array ((Vala.ArrayType) vntype, arr); - } else { - arr.data_type = create_type_reference (vntype, arr); - } - - return arr; - } - - private TypeReference create_type_reference (Vala.DataType? vtyperef, Item parent) { - bool is_nullable = vtyperef != null && vtyperef.nullable && !(vtyperef is Vala.GenericType) && !(vtyperef is Vala.PointerType); - string? signature = (vtyperef != null && vtyperef.data_type != null)? Vala.GVariantModule.get_dbus_signature (vtyperef.data_type) : null; - bool pass_ownership = type_reference_pass_ownership (vtyperef); - Ownership ownership = get_type_reference_ownership (vtyperef); - bool is_dynamic = vtyperef != null && vtyperef.is_dynamic; - - TypeReference type_ref = new TypeReference (parent, ownership, pass_ownership, is_dynamic, is_nullable, signature, vtyperef); - - if (vtyperef is Vala.PointerType) { - type_ref.data_type = create_pointer ((Vala.PointerType) vtyperef, type_ref); - } else if (vtyperef is Vala.ArrayType) { - type_ref.data_type = create_array ((Vala.ArrayType) vtyperef, type_ref); - } - - // type parameters: - if (vtyperef != null) { - foreach (Vala.DataType vdtype in vtyperef.get_type_arguments ()) { - var type_param = create_type_reference (vdtype, type_ref); - type_ref.add_type_argument (type_param); - } - } - - return type_ref; - } - - - - // - // Translation helpers: - // - - private SourceComment? create_comment (Vala.Comment? comment) { - if (comment != null) { - Vala.SourceReference pos = comment.source_reference; - SourceFile file = files.get (pos.file); - return new SourceComment (comment.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column); - } - - return null; - } - - private string get_method_name (Vala.Method element) { - if (element is Vala.CreationMethod) { - if (element.name == ".new") { - return element.parent_symbol.name; - } else { - return element.parent_symbol.name + "." + element.name; - } - } - - return element.name; - } - - private PackageMetaData? get_package_meta_data (Package pkg) { - foreach (PackageMetaData data in packages) { - if (data.package == pkg) { - return data; - } - } - - return null; - } - - private PackageMetaData register_package (Package package) { - PackageMetaData meta_data = new PackageMetaData (package); - tree.add_package (package); - packages.add (meta_data); - return meta_data; - } - - private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) { - SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ()); - files.set (source_file, file); - - meta_data.register_source_file (source_file); - return file; - } - - private SourceFile? get_source_file (Vala.Symbol symbol) { - Vala.SourceReference source_ref = symbol.source_reference; - if (source_ref == null) { - return null; - } - - SourceFile file = files.get (source_ref.file); - assert (file != null); - return file; - } - - private Package? find_package_for_file (Vala.SourceFile source_file) { - foreach (PackageMetaData pkg in this.packages) { - if (pkg.is_package_for_file (source_file)) { - return pkg.package; - } - } - - return null; - } - - - private Namespace get_namespace (Package pkg, Vala.Symbol symbol, SourceFile? file) { - // Find the closest namespace in our vala-tree - Vala.Symbol namespace_symbol = symbol; - while (!(namespace_symbol is Vala.Namespace)) { - namespace_symbol = namespace_symbol.parent_symbol; - } - - PackageMetaData? meta_data = get_package_meta_data (pkg); - assert (meta_data != null); - - return meta_data.get_namespace ((Vala.Namespace) namespace_symbol, file); - } - - private MethodBindingType get_method_binding_type (Vala.Method element) { - if (element.is_inline) { - return MethodBindingType.INLINE; - } else if (element.is_abstract) { - return MethodBindingType.ABSTRACT; - } else if (element.is_virtual) { - return MethodBindingType.VIRTUAL; - } else if (element.overrides) { - return MethodBindingType.OVERRIDE; - } else if (element.is_inline) { - return MethodBindingType.INLINE; - } else if (element.binding == Vala.MemberBinding.INSTANCE) { - return MethodBindingType.STATIC; - } - return MethodBindingType.UNMODIFIED; - } - - - private SymbolAccessibility get_access_modifier(Vala.Symbol symbol) { - switch (symbol.access) { - case Vala.SymbolAccessibility.PROTECTED: - return SymbolAccessibility.PROTECTED; - - case Vala.SymbolAccessibility.INTERNAL: - return SymbolAccessibility.INTERNAL; - - case Vala.SymbolAccessibility.PRIVATE: - return SymbolAccessibility.PRIVATE; - - case Vala.SymbolAccessibility.PUBLIC: - return SymbolAccessibility.PUBLIC; - - default: - error ("Unknown symbol accessibility modifier found"); - } - } - - private PropertyAccessorType get_property_accessor_type (Vala.PropertyAccessor element) { - if (element.construction) { - return PropertyAccessorType.CONSTRUCT; - } else if (element.writable) { - return PropertyAccessorType.SET; - } else if (element.readable) { - return PropertyAccessorType.GET; - } - - error ("Unknown symbol accessibility type"); - } - - private bool type_reference_pass_ownership (Vala.DataType? element) { - if (element == null) { - return false; - } - - Vala.CodeNode? node = element.parent_node; - if (node == null) { - return false; - } - if (node is Vala.Parameter) { - return (((Vala.Parameter)node).direction == Vala.ParameterDirection.IN && - ((Vala.Parameter)node).variable_type.value_owned); - } - if (node is Vala.Property) { - return ((Vala.Property)node).property_type.value_owned; - } - - return false; - } - - private bool is_type_reference_unowned (Vala.DataType? element) { - if (element == null) { - return false; - } - - // non ref counted types are weak, not unowned - if (element.data_type is Vala.TypeSymbol && ((Vala.TypeSymbol) element.data_type).is_reference_counting () == true) { - return false; - } - - // FormalParameters are weak by default - return (element.parent_node is Vala.Parameter == false)? element.is_weak () : false; - } - - private bool is_type_reference_owned (Vala.DataType? element) { - if (element == null) { - return false; - } - - Vala.CodeNode parent = element.parent_node; - - // parameter: - if (parent is Vala.Parameter) { - if (((Vala.Parameter)parent).direction != Vala.ParameterDirection.IN) { - return false; - } - return ((Vala.Parameter)parent).variable_type.value_owned; - } - - return false; - } - - private bool is_type_reference_weak (Vala.DataType? element) { - if (element == null) { - return false; - } - - // non ref counted types are unowned, not weak - if (element.data_type is Vala.TypeSymbol && ((Vala.TypeSymbol) element.data_type).is_reference_counting () == false) { - return false; - } - - // FormalParameters are weak by default - return (element.parent_node is Vala.Parameter == false)? element.is_weak () : false; - } - - private Ownership get_type_reference_ownership (Vala.DataType? element) { - if (is_type_reference_owned (element)) { - return Ownership.OWNED; - } else if (is_type_reference_weak (element)) { - return Ownership.WEAK; - } else if (is_type_reference_unowned (element)) { - return Ownership.UNOWNED; - } - - return Ownership.DEFAULT; - } - - private Ownership get_property_ownership (Vala.PropertyAccessor element) { - if (element.value_type.value_owned) { - return Ownership.OWNED; - } - - // the exact type (weak, unowned) does not matter - return Ownership.UNOWNED; - } - - private PropertyBindingType get_property_binding_type (Vala.Property element) { - if (element.is_abstract) { - return PropertyBindingType.ABSTRACT; - } else if (element.is_virtual) { - return PropertyBindingType.VIRTUAL; - } else if (element.overrides) { - return PropertyBindingType.OVERRIDE; - } - - return PropertyBindingType.UNMODIFIED; - } - - private FormalParameterType get_formal_parameter_type (Vala.Parameter element) { - if (element.direction == Vala.ParameterDirection.OUT) { - return FormalParameterType.OUT; - } else if (element.direction == Vala.ParameterDirection.REF) { - return FormalParameterType.REF; - } else if (element.direction == Vala.ParameterDirection.IN) { - return FormalParameterType.IN; - } - - error ("Unknown formal parameter type"); - } - - - // - // Vala tree creation: - // - - private bool add_package (Vala.CodeContext context, string pkg) { - if (context.has_package (pkg)) { - // ignore multiple occurences of the same package - return true; - } - - var package_path = context.get_vapi_path (pkg) ?? context.get_gir_path (pkg); - if (package_path == null) { - Vala.Report.error (null, "Package `%s' not found in specified Vala API directories or GObject-Introspection GIR directories".printf (pkg)); - return false; - } - - context.add_package (pkg); - - var vfile = new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, package_path); - context.add_source_file (vfile); - Package vdpkg = new Package (vfile, pkg, true, null); - register_source_file (register_package (vdpkg), vfile); - - add_deps (context, Path.build_filename (Path.get_dirname (package_path), "%s.deps".printf (pkg)), pkg); - return true; - } - - private void add_deps (Vala.CodeContext context, string file_path, string pkg_name) { - if (FileUtils.test (file_path, FileTest.EXISTS)) { - try { - string deps_content; - ulong deps_len; - FileUtils.get_contents (file_path, out deps_content, out deps_len); - foreach (string dep in deps_content.split ("\n")) { - dep.strip (); - if (dep != "") { - if (!add_package (context, dep)) { - Vala.Report.error (null, "%s, dependency of %s, not found in specified Vala API directories".printf (dep, pkg_name)); - } - } - } - } catch (FileError e) { - Vala.Report.error (null, "Unable to read dependency file: %s".printf (e.message)); - } - } - } - - /** - * Adds the specified packages to the list of used packages. - * - * @param context The code context - * @param packages a list of package names - */ - private void add_depencies (Vala.CodeContext context, string[] packages) { - foreach (string package in packages) { - if (!add_package (context, package)) { - Vala.Report.error (null, "Package `%s' not found in specified Vala API directories or GObject-Introspection GIR directories".printf (package)); - } - } - } - - /** - * Add the specified source file to the context. Only .vala, .vapi, .gs, - * and .c files are supported. - */ - private void add_documented_files (Vala.CodeContext context, string[] sources) { - if (sources == null) { - return; - } - - foreach (string source in sources) { - if (FileUtils.test (source, FileTest.EXISTS)) { - var rpath = realpath (source); - if (source.has_suffix (".vala") || source.has_suffix (".gs")) { - var source_file = new Vala.SourceFile (context, Vala.SourceFileType.SOURCE, rpath); - - if (source_package == null) { - source_package = register_package (new Package (source_file, settings.pkg_name, false, null)); - } - - register_source_file (source_package, source_file); - - if (context.profile == Vala.Profile.POSIX) { - // import the Posix namespace by default (namespace of backend-specific standard library) - var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "Posix", null)); - source_file.add_using_directive (ns_ref); - context.root.add_using_directive (ns_ref); - } else if (context.profile == Vala.Profile.GOBJECT) { - // import the GLib namespace by default (namespace of backend-specific standard library) - var ns_ref = new Vala.UsingDirective (new Vala.UnresolvedSymbol (null, "GLib", null)); - source_file.add_using_directive (ns_ref); - context.root.add_using_directive (ns_ref); - } - - context.add_source_file (source_file); - } else if (source.has_suffix (".vapi")) { - string file_name = Path.get_basename (source); - file_name = file_name.substring (0, file_name.length - ".vapi".length); - - var vfile = new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, rpath); - Package vdpkg = new Package (vfile, file_name, true, null); - context.add_source_file (vfile); - - register_source_file (register_package (vdpkg), vfile); - - add_deps (context, Path.build_filename (Path.get_dirname (source), "%s.deps".printf (file_name)), file_name); - } else if (source.has_suffix (".c")) { - context.add_c_source_file (rpath); - tree.add_external_c_files (rpath); - } else { - Vala.Report.error (null, "%s is not a supported source file type. Only .vala, .vapi, .gs, and .c files are supported.".printf (source)); - } - } else { - Vala.Report.error (null, "%s not found".printf (source)); - } - } - } - - private Vala.CodeContext create_valac_tree (Settings settings) { - // init context: - var context = new Vala.CodeContext (); - Vala.CodeContext.push (context); - - - // settings: - context.experimental = settings.experimental; - context.experimental_non_null = settings.experimental || settings.experimental_non_null; - context.vapi_directories = settings.vapi_directories; - context.report.enable_warnings = settings.verbose; - - if (settings.basedir == null) { - context.basedir = realpath ("."); - } else { - context.basedir = realpath (settings.basedir); - } - - if (settings.directory != null) { - context.directory = realpath (settings.directory); - } else { - context.directory = context.basedir; - } - - - // add default packages: - if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == null) { - context.profile = Vala.Profile.GOBJECT; - context.add_define ("GOBJECT"); - } - - - if (settings.defines != null) { - foreach (string define in settings.defines) { - context.add_define (define); - } - } - - if (context.profile == Vala.Profile.POSIX) { - // default package - if (!add_package (context, "posix")) { - Vala.Report.error (null, "posix not found in specified Vala API directories"); - } - } else if (context.profile == Vala.Profile.GOBJECT) { - int glib_major = 2; - int glib_minor = 12; - - context.target_glib_major = glib_major; - context.target_glib_minor = glib_minor; - if (context.target_glib_major != 2) { - Vala.Report.error (null, "This version of valac only supports GLib 2"); - } - - // default packages - if (!this.add_package (context, "glib-2.0")) { // - Vala.Report.error (null, "glib-2.0 not found in specified Vala API directories"); - } - - if (!this.add_package (context, "gobject-2.0")) { // - Vala.Report.error (null, "gobject-2.0 not found in specified Vala API directories"); - } - } - - - // add user defined files: - add_depencies (context, settings.packages); - if (reporter.errors > 0) { - return context; - } - - add_documented_files (context, settings.source_files); - if (reporter.errors > 0) { - return context; - } - - - // parse vala-code: - Vala.Parser parser = new Vala.Parser (); - - parser.parse (context); - if (context.report.get_errors () > 0) { - return context; - } - - - // check context: - context.check (); - if (context.report.get_errors () > 0) { - return context; - } - - return context; - } - - - - // - // Valadoc tree creation: - // - - private void process_children (Api.Node node, Vala.Symbol element) { - Api.Node old_node = current_node; - current_node = node; - element.accept_children (this); - current_node = old_node; - } - - private Api.Node get_parent_node_for (Vala.Symbol element) { - if (current_node != null) { - return current_node; - } - - Vala.SourceFile vala_source_file = element.source_reference.file; - Package package = find_package_for_file (vala_source_file); - SourceFile? source_file = get_source_file (element); - - return get_namespace (package, element, source_file); - } - - /** - * {@inheritDoc} - */ - public override void visit_namespace (Vala.Namespace element) { - element.accept_children (this); - } - - /** - * {@inheritDoc} - */ - public override void visit_class (Vala.Class element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - bool is_basic_type = element.base_class == null && element.name == "string"; - - Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name (element), element.get_param_spec_function (), element.get_type_id (), element.get_ref_function (), element.get_unref_function (), element.get_take_value_function (), element.get_get_value_function (), element.get_set_value_function (), element.is_fundamental (), element.is_abstract, is_basic_type, element); - symbol_map.set (element, node); - parent.add_child (node); - - // relations - foreach (Vala.DataType vala_type_ref in element.get_base_types ()) { - var type_ref = create_type_reference (vala_type_ref, node); - - if (vala_type_ref.data_type is Vala.Interface) { - node.add_interface (type_ref); - } else { - node.base_type = type_ref; - } - } - - process_children (node, element); - - // save GLib.Error - if (glib_error == null && node.get_full_name () == "GLib.Error") { - glib_error = node; - } - } - - /** - * {@inheritDoc} - */ - public override void visit_interface (Vala.Interface element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Interface node = new Interface (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name (element), element); - symbol_map.set (element, node); - parent.add_child (node); - - // prerequisites: - foreach (Vala.DataType vala_type_ref in element.get_prerequisites ()) { - TypeReference type_ref = create_type_reference (vala_type_ref, node); - if (vala_type_ref.data_type is Vala.Interface) { - node.add_interface (type_ref); - } else { - node.base_type = type_ref; - } - } - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_struct (Vala.Struct element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - bool is_basic_type = element.base_type == null && (element.is_boolean_type () || element.is_floating_type () || element.is_integer_type ()); - - Struct node = new Struct (parent, file, element.name, get_access_modifier(element), comment, element.get_cname(), element.get_dup_function (), element.get_free_function (), is_basic_type, element); - symbol_map.set (element, node); - parent.add_child (node); - - // parent type: - Vala.ValueType? basetype = element.base_type as Vala.ValueType; - if (basetype != null) { - node.base_type = create_type_reference (basetype, node); - } - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_field (Vala.Field element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Field node = new Field (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element.binding == Vala.MemberBinding.STATIC, element.is_volatile, element); - node.field_type = create_type_reference (element.variable_type, node); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_property (Vala.Property element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Property node = new Property (parent, file, element.name, get_access_modifier(element), comment, element.nick, Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.is_dbus_visible (element), get_property_binding_type (element), element); - node.property_type = create_type_reference (element.property_type, node); - symbol_map.set (element, node); - parent.add_child (node); - - // Process property type - if (element.get_accessor != null) { - var accessor = element.get_accessor; - node.getter = new PropertyAccessor (node, file, element.name, get_access_modifier(element), accessor.get_cname(), get_property_accessor_type (accessor), get_property_ownership (accessor), accessor); - } - - if (element.set_accessor != null) { - var accessor = element.set_accessor; - node.setter = new PropertyAccessor (node, file, element.name, get_access_modifier(element), accessor.get_cname(), get_property_accessor_type (accessor), get_property_ownership (accessor), accessor); - } - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_creation_method (Vala.CreationMethod element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Method node = new Method (parent, file, get_method_name (element), get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.dbus_result_name (element), (element.coroutine)? element.get_finish_cname () : null, get_method_binding_type (element), element.coroutine, Vala.GDBusServerModule.is_dbus_visible (element), element is Vala.CreationMethod, element); - node.return_type = create_type_reference (element.return_type, node); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_method (Vala.Method element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Method node = new Method (parent, file, get_method_name (element), get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.dbus_result_name (element), (element.coroutine)? element.get_finish_cname () : null, get_method_binding_type (element), element.coroutine, Vala.GDBusServerModule.is_dbus_visible (element), element is Vala.CreationMethod, element); - node.return_type = create_type_reference (element.return_type, node); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_signal (Vala.Signal element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Signal node = new Api.Signal (parent, file, element.name, get_access_modifier(element), comment, element.get_cname(), Vala.GDBusModule.get_dbus_name_for_member (element), Vala.GDBusServerModule.is_dbus_visible (element), element.is_virtual, element); - node.return_type = create_type_reference (element.return_type, node); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_delegate (Vala.Delegate element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Delegate node = new Delegate (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element.has_target, element); - node.return_type = create_type_reference (element.return_type, node); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_enum (Vala.Enum element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Symbol node = new Enum (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_enum_value (Vala.EnumValue element) { - Api.Enum parent = (Enum) get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Symbol node = new Api.EnumValue (parent, file, element.name, comment, element.get_cname (), element); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_constant (Vala.Constant element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Constant node = new Constant (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), element); - node.constant_type = create_type_reference (element.type_reference, node); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_error_domain (Vala.ErrorDomain element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Symbol node = new ErrorDomain (parent, file, element.name, get_access_modifier(element), comment, element.get_cname(), Vala.GDBusModule.get_dbus_name (element), element); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_error_code (Vala.ErrorCode element) { - Api.ErrorDomain parent = (ErrorDomain) get_parent_node_for (element); - SourceFile? file = get_source_file (element); - SourceComment? comment = create_comment (element.comment); - - Symbol node = new Api.ErrorCode (parent, file, element.name, comment, element.get_cname (), Vala.GDBusModule.get_dbus_name_for_member (element), element); - symbol_map.set (element, node); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_type_parameter (Vala.TypeParameter element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - - Symbol node = new TypeParameter (parent, file, element.name, element); - parent.add_child (node); - - process_children (node, element); - } - - /** - * {@inheritDoc} - */ - public override void visit_formal_parameter (Vala.Parameter element) { - Api.Node parent = get_parent_node_for (element); - SourceFile? file = get_source_file (element); - - FormalParameter node = new FormalParameter (parent, file, element.name, get_access_modifier(element), get_formal_parameter_type (element), element.ellipsis, element); - node.parameter_type = create_type_reference (element.variable_type, node); - parent.add_child (node); - - process_children (node, element); - } - - - // - // startpoint: - // - - public Api.Tree? build (Settings settings, ErrorReporter reporter) { - this.tree = new Api.Tree (reporter, settings); - this.settings = settings; - this.reporter = reporter; - - var context = create_valac_tree (settings); - - reporter.warnings_offset = context.report.get_warnings (); - reporter.errors_offset = context.report.get_errors (); - - if (context == null) { - return null; - } +[CCode (has_target = false)] +public delegate Type Valadoc.DriverRegisterFunction (GLib.TypeModule module); - context.accept(this); - if (reporter.errors > 0) { - return null; - } - SymbolResolver resolver = new SymbolResolver (symbol_map, glib_error); - this.tree.accept (resolver); +public interface Valadoc.Driver : Object { - return tree; - } + public abstract Api.Tree? build (Settings settings, ErrorReporter reporter); } diff --git a/src/libvaladoc/api/interface.vala b/src/libvaladoc/api/interface.vala index 236b14d15..b8c339ee9 100755 --- a/src/libvaladoc/api/interface.vala +++ b/src/libvaladoc/api/interface.vala @@ -140,11 +140,11 @@ public class Valadoc.Api.Interface : TypeSymbol { return _known_related_interfaces; } - internal void register_related_interface (Interface iface) { + public void register_related_interface (Interface iface) { _known_related_interfaces.add (iface); } - internal void register_implementation (Class cl) { + public void register_implementation (Class cl) { _known_implementations.add (cl); } diff --git a/src/libvaladoc/api/node.vala b/src/libvaladoc/api/node.vala index 49671bc4e..48cb6009c 100755 --- a/src/libvaladoc/api/node.vala +++ b/src/libvaladoc/api/node.vala @@ -114,7 +114,7 @@ public abstract class Valadoc.Api.Node : Item, Browsable, Documentation, Compara return file.relative_path; } - internal void add_child (Symbol child) { + public void add_child (Symbol child) { if (child.name != null) { per_name_children.set (child.name, child); } else { diff --git a/src/libvaladoc/api/signaturebuilder.vala b/src/libvaladoc/api/signaturebuilder.vala index 801afe072..f589a0b6a 100755 --- a/src/libvaladoc/api/signaturebuilder.vala +++ b/src/libvaladoc/api/signaturebuilder.vala @@ -58,6 +58,20 @@ public class Valadoc.Api.SignatureBuilder { return this; } + /** + * Adds highlighted text onto the end of the builder. + * + * @param literal a string + * @param spaced add a space at the front of the string if necessary + * @return this + */ + public SignatureBuilder append_highlighted (string text, bool spaced = true) { + string content = (last_appended != null && spaced ? " " : "") + text; + Run inner = new Run (Run.Style.ITALIC); + inner.content.add (new Text (content)); + return append_content (inner, spaced); + } + /** * Adds a Inline onto the end of the builder. * diff --git a/src/libvaladoc/api/tree.vala b/src/libvaladoc/api/tree.vala index 8c28e66fb..c66205834 100755 --- a/src/libvaladoc/api/tree.vala +++ b/src/libvaladoc/api/tree.vala @@ -40,8 +40,7 @@ public class Valadoc.Api.Tree { private ErrorReporter reporter; private CTypeResolver _cresolver = null; - // TODO schöner machen - internal void add_package(Package package) { + public void add_package(Package package) { this.packages.add (package); } @@ -67,7 +66,7 @@ public class Valadoc.Api.Tree { return external_c_files.read_only_view; } - internal void add_external_c_files (string name) { + public void add_external_c_files (string name) { external_c_files.add (name); } diff --git a/src/libvaladoc/moduleloader.vala b/src/libvaladoc/moduleloader.vala index 8743aecb0..72297a9ea 100755 --- a/src/libvaladoc/moduleloader.vala +++ b/src/libvaladoc/moduleloader.vala @@ -1,6 +1,7 @@ /* moduleloader.vala * * Copyright (C) 2008-2009 Florian Brosch + * Copyright (C) 2011 Florian Brosch * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,16 +25,21 @@ using Gee; [CCode (has_target = false)] -public delegate void Valadoc.TagletRegisterFunction (ModuleLoader loader); +public delegate void Valadoc.TagletRegisterFunction (ModuleLoader loader); + -public class Valadoc.ModuleLoader : TypeModule { - public Doclet doclet; +public class Valadoc.ModuleLoader : TypeModule { public HashMap taglets = new HashMap (GLib.str_hash, GLib.str_equal); + private Module drivermodule; + private Type drivertype; + public Driver driver; + private Module docletmodule; private Type doclettype; + public Doclet doclet; public ModuleLoader () { Object (); @@ -65,7 +71,27 @@ public class Valadoc.ModuleLoader : TypeModule { Valadoc.DocletRegisterFunction doclet_register_function = (Valadoc.DocletRegisterFunction) function; doclettype = doclet_register_function (this); - this.doclet = (Doclet)GLib.Object.new (doclettype); + this.doclet = (Doclet) GLib.Object.new (doclettype); + return true; + } + + + public bool load_driver (string path) { + void* function; + + drivermodule = Module.open (Module.build_path (path, "libdriver"), ModuleFlags.BIND_LAZY | ModuleFlags.BIND_LOCAL); + if (drivermodule == null) { + return false; + } + + drivermodule.symbol("register_plugin", out function); + if (function == null) { + return false; + } + + Valadoc.DriverRegisterFunction driver_register_function = (Valadoc.DriverRegisterFunction) function; + drivertype = driver_register_function (this); + this.driver = (Driver) GLib.Object.new (drivertype); return true; } } diff --git a/src/valadoc/Makefile.am b/src/valadoc/Makefile.am index 67bae8b9a..8b34324fb 100755 --- a/src/valadoc/Makefile.am +++ b/src/valadoc/Makefile.am @@ -2,7 +2,7 @@ NULL = AM_CFLAGS = \ - -DPACKAGE_DATADIR=\"$(libdir)/valadoc/plugins\" \ + -DPACKAGE_DATADIR=\"$(libdir)/valadoc\" \ -DPACKAGE_VERSION=\"$(VERSION)\" \ -I ../libvaladoc/ \ $(GLIB_CFLAGS) \ diff --git a/src/valadoc/valadoc.vala b/src/valadoc/valadoc.vala index 36235c694..02684b3e2 100755 --- a/src/valadoc/valadoc.vala +++ b/src/valadoc/valadoc.vala @@ -31,11 +31,12 @@ using Gee; public class ValaDoc : Object { private static string wikidirectory = null; private static string pkg_version = null; - private static string pluginpath = null; + private static string docletpath = null; [CCode (array_length = false, array_null_terminated = true)] private static string[] pluginargs; private static string directory = null; private static string pkg_name = null; + private static string driverpath = null; private static bool add_inherited = false; private static bool _protected = true; @@ -71,7 +72,7 @@ public class ValaDoc : Object { { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." }, { "importdir", 0, 0, OptionArg.FILENAME_ARRAY, ref import_directories, "Look for external documentation in DIRECTORY", "DIRECTORY..." }, { "profile", 0, 0, OptionArg.STRING, ref profile, "Use the given profile instead of the default", "PROFILE" }, - { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null }, + { "driver", 0, 0, OptionArg.NONE, ref driverpath, "Display version number", null }, { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." }, { "import", 0, 0, OptionArg.STRING_ARRAY, ref import_packages, "Include binding for PACKAGE", "PACKAGE..." }, @@ -79,82 +80,106 @@ public class ValaDoc : Object { { "wiki", 0, 0, OptionArg.FILENAME, ref wikidirectory, "Wiki directory", "DIRECTORY" }, { "deps", 0, 0, OptionArg.NONE, ref with_deps, "Adds packages to the documentation", null }, + { "doclet-arg", 'X', 0, OptionArg.STRING_ARRAY, ref pluginargs, "Pass arguments to the doclet", "ARG" }, - { "doclet", 0, 0, OptionArg.STRING, ref pluginpath, "Name of an included doclet or path to custom doclet", "PLUGIN"}, + { "doclet", 0, 0, OptionArg.STRING, ref docletpath, "Name of an included doclet or path to custom doclet", "PLUGIN"}, + { "no-protected", 0, OptionFlags.REVERSE, OptionArg.NONE, ref _protected, "Removes protected elements from documentation", null }, { "internal", 0, 0, OptionArg.NONE, ref _internal, "Adds internal elements to documentation", null }, { "private", 0, 0, OptionArg.NONE, ref _private, "Adds private elements to documentation", null }, // { "inherit", 0, 0, OptionArg.NONE, ref add_inherited, "Adds inherited elements to a class", null }, + { "package-name", 0, 0, OptionArg.STRING, ref pkg_name, "package name", "NAME" }, { "package-version", 0, 0, OptionArg.STRING, ref pkg_version, "package version", "VERSION" }, + { "force", 0, 0, OptionArg.NONE, ref force, "force", null }, { "verbose", 0, 0, OptionArg.NONE, ref verbose, "Show all warnings", null }, { "", 0, 0, OptionArg.FILENAME_ARRAY, ref tsources, null, "FILE..." }, + { null } }; private static int quit (ErrorReporter reporter) { - if ( reporter.errors == 0) { + if (reporter.errors == 0) { stdout.printf ("Succeeded - %d warning(s)\n", reporter.warnings); return 0; - } - else { + } else { stdout.printf ("Failed: %d error(s), %d warning(s)\n", reporter.errors, reporter.warnings); return 1; } } private static bool check_pkg_name () { - if (pkg_name == null) + if (pkg_name == null) { return true; + } - if (pkg_name == "glib-2.0" || pkg_name == "gobject-2.0") + if (pkg_name == "glib-2.0" || pkg_name == "gobject-2.0") { return false; + } foreach (string package in tsources) { - if (pkg_name == package) + if (pkg_name == package) { return false; + } } return true; } private string get_pkg_name () { if (this.pkg_name == null) { - if (this.directory.has_suffix ("/")) + if (this.directory.has_suffix ("/")) { this.pkg_name = GLib.Path.get_dirname (this.directory); - else + } else { this.pkg_name = GLib.Path.get_basename (this.directory); + } } return this.pkg_name; } - private ModuleLoader? create_module_loader (ErrorReporter reporter) { - string fulldirpath = ""; + private string get_plugin_dir (string? pluginpath, string subdir, string default_pkg) { if (pluginpath == null) { - fulldirpath = build_filename (Config.plugin_dir, "html"); - } else if (is_absolute (pluginpath ) == false) { + return build_filename (Config.plugin_dir, subdir, default_pkg); + } + + if (is_absolute (pluginpath) == false) { // Test to see if the plugin exists in the expanded path and then fallback // to using the configured plugin directory string local_path = build_filename (Environment.get_current_dir(), pluginpath); - if ( FileUtils.test(local_path, FileTest.EXISTS)) { - fulldirpath = local_path; + if (FileUtils.test(local_path, FileTest.EXISTS)) { + return local_path; } else { - fulldirpath = build_filename (Config.plugin_dir, pluginpath); + return build_filename (Config.plugin_dir, subdir, pluginpath); } - } else { - fulldirpath = pluginpath; } + return pluginpath; + } + private ModuleLoader? create_module_loader (ErrorReporter reporter) { ModuleLoader modules = new ModuleLoader (); Taglets.init (modules); - bool tmp = modules.load_doclet (fulldirpath); + + // doclet: + string pluginpath = get_plugin_dir (docletpath, "doclets", "html"); + bool tmp = modules.load_doclet (pluginpath); if (tmp == false) { - reporter.simple_error ("failed to load plugin"); + reporter.simple_error ("failed to load doclet"); return null; } + + // driver: + pluginpath = get_plugin_dir (driverpath, "drivers", "0.13.x"); + tmp = modules.load_driver (pluginpath); + if (tmp == false) { + reporter.simple_error ("failed to load driver"); + return null; + } + + assert (modules.driver != null && modules.doclet != null); + return modules; } @@ -186,8 +211,15 @@ public class ValaDoc : Object { settings.defines = defines; + // load plugins: + ModuleLoader? modules = create_module_loader (reporter); + if (reporter.errors > 0 || modules == null) { + return quit (reporter); + } + + // Create tree: - Valadoc.Api.Driver driver = new Valadoc.Api.Driver (); + Valadoc.Driver driver = modules.driver; Valadoc.Api.Tree doctree = driver.build (settings, reporter); if (reporter.errors > 0) { @@ -196,11 +228,6 @@ public class ValaDoc : Object { // process documentation - ModuleLoader? modules = create_module_loader (reporter); - if (reporter.errors > 0 || modules == null) { - return quit (reporter); - } - Valadoc.DocumentationParser docparser = new Valadoc.DocumentationParser (settings, reporter, doctree, modules); if (!doctree.create_tree()) { return quit (reporter); @@ -233,8 +260,7 @@ public class ValaDoc : Object { opt_context.set_help_enabled (true); opt_context.add_main_entries (options, null); opt_context.parse (ref args); - } - catch (OptionError e) { + } catch (OptionError e) { reporter.simple_error (e.message); stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]); return quit (reporter); @@ -262,8 +288,7 @@ public class ValaDoc : Object { reporter.simple_error ("Can't remove directory."); return quit (reporter); } - } - else { + } else { reporter.simple_error ("File already exists"); return quit (reporter); }