diff options
author | Hans Bolinder <[email protected]> | 2011-05-05 14:22:18 +0200 |
---|---|---|
committer | Hans Bolinder <[email protected]> | 2011-05-16 13:33:08 +0200 |
commit | 38b2f44764e79a34048f686d98b6d741d18738d2 (patch) | |
tree | edc44f6a2f7a71e37cd1c18d113817a671cfe6b0 /lib/erl_docgen/priv/xsl/db_pdf.xsl | |
parent | e375165f6421c86fb245843d787e021d5b7dd00d (diff) | |
download | otp-38b2f44764e79a34048f686d98b6d741d18738d2.tar.gz otp-38b2f44764e79a34048f686d98b6d741d18738d2.tar.bz2 otp-38b2f44764e79a34048f686d98b6d741d18738d2.zip |
Improve erl_docgen's support for Dialyzer specs and types
The support for using Dialyzer specifications and types has been
improved.
Diffstat (limited to 'lib/erl_docgen/priv/xsl/db_pdf.xsl')
-rw-r--r-- | lib/erl_docgen/priv/xsl/db_pdf.xsl | 451 |
1 files changed, 310 insertions, 141 deletions
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl index f500cd3fee..5119e3e36a 100644 --- a/lib/erl_docgen/priv/xsl/db_pdf.xsl +++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl @@ -21,6 +21,8 @@ --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:exsl="http://exslt.org/common" + extension-element-prefixes="exsl" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="xml" indent="yes"/> @@ -28,45 +30,66 @@ <xsl:include href="db_pdf_params.xsl"/> <!-- Start of Dialyzer type/spec tags. - See also the template matching "name" and the template "bookmarks6" + See also the templates matching "name" and "seealso" as well as + the template "bookmarks6" --> <xsl:param name="specs_file" select="''"/> <xsl:variable name="i" select="document($specs_file)"></xsl:variable> <xsl:template name="err"> + <xsl:param name="f"/> <xsl:param name="m"/> <xsl:param name="n"/> <xsl:param name="a"/> <xsl:param name="s"/> <xsl:message terminate="yes"> - Error <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if> - <xsl:value-of - select="$n"/>/<xsl:value-of - select="$a"/>: <xsl:value-of select="$s"/> + Error <xsl:if test="$f != ''">in <xsl:value-of select ="$f"/>:</xsl:if> + <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if> + <xsl:value-of select="$n"/> + <xsl:if test="$a != ''">/<xsl:value-of + select ="$a"/></xsl:if>: <xsl:value-of select="$s"/> </xsl:message> </xsl:template> - <xsl:template name="spec_name"> + <xsl:template name="find_spec"> <xsl:variable name="curModule" select="ancestor::erlref/module"/> <xsl:variable name="mod" select="@mod"/> <xsl:variable name="name" select="@name"/> <xsl:variable name="arity" select="@arity"/> - <xsl:variable name="clause" select="@clause"/> + <xsl:variable name="clause_i" select="@clause_i"/> <xsl:variable name="spec0" select= "$i/specs/module[@name=$curModule]/spec [name=$name and arity=$arity and (string-length($mod) = 0 or module = $mod)]"/> - <xsl:variable name="spec" select="$spec0[string-length($clause) = 0 - or position() = $clause]"/> - <xsl:if test="count($spec) = 0"> + <xsl:variable name="spec" select="$spec0[string-length($clause_i) = 0 + or position() = $clause_i]"/> + + <xsl:if test="count($spec) != 1"> + <xsl:variable name="why"> + <xsl:choose> + <xsl:when test="count($spec) > 1">ambiguous spec</xsl:when> + <xsl:when test="count($spec) = 0">unknown spec</xsl:when> + </xsl:choose> + </xsl:variable> <xsl:call-template name="err"> + <xsl:with-param name="f" select="$curModule"/> <xsl:with-param name="m" select="$mod"/> <xsl:with-param name="n" select="$name"/> <xsl:with-param name="a" select="$arity"/> - <xsl:with-param name="s">unknown spec</xsl:with-param> + <xsl:with-param name="s" select="$why"/> </xsl:call-template> </xsl:if> + <xsl:copy-of select="$spec"/> + </xsl:template> + + <xsl:template name="spec_name"> + <xsl:variable name="name" select="@name"/> + <xsl:variable name="arity" select="@arity"/> + <xsl:variable name="spec0"> + <xsl:call-template name="find_spec"/> + </xsl:variable> + <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/> <xsl:choose> <xsl:when test="ancestor::cref"> @@ -76,78 +99,175 @@ </xsl:when> <xsl:when test="ancestor::erlref"> <fo:block id="{generate-id()}"> - <xsl:choose> - <xsl:when test="string(@with_guards) = 'no'"> - <xsl:apply-templates select="$spec/contract/clause/head"/> - </xsl:when> - <xsl:otherwise> - <xsl:call-template name="contract"> - <xsl:with-param name="contract" select="$spec/contract"/> - </xsl:call-template> - </xsl:otherwise> - </xsl:choose> + <xsl:apply-templates select="$spec/contract/clause/head"/> </fo:block> </xsl:when> </xsl:choose> </xsl:template> - <xsl:template name="contract"> - <xsl:param name="contract"/> - <xsl:call-template name="clause"> - <xsl:with-param name="clause" select="$contract/clause"/> - </xsl:call-template> + <xsl:template match="head"> + <fo:block xsl:use-attribute-sets="function-name"> + <xsl:apply-templates/> + </fo:block> </xsl:template> - <xsl:template name="clause"> - <xsl:param name="clause"/> + <!-- The *last* <name name="..." arity=".."/> --> + <xsl:template match="name" mode="types"> + <xsl:variable name="name" select="@name"/> + <xsl:variable name="arity" select="@arity"/> + <xsl:variable name="spec0"> + <xsl:call-template name="find_spec"/> + </xsl:variable> + <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/> + <xsl:variable name="clause" select="$spec/contract/clause"/> + <xsl:variable name="type_desc" select="../type_desc"/> - <xsl:for-each select="$clause"> - <xsl:apply-templates select="head"/> - <xsl:if test="count(guard) > 0"> - <xsl:call-template name="guard"> - <xsl:with-param name="guard" select="guard"/> + <!-- $type is data types to be presented as guards ("local types") --> + <xsl:variable name="type" + select="../type[string-length(@name) > 0 + or string-length(@variable) > 0]"/> + <xsl:variable name="type_variables" + select ="$type[string-length(@variable) > 0]"/> + <xsl:variable name="local_types" + select ="$type[string-length(@name) > 0]"/> + <xsl:variable name="output_subtypes" select="count($type_variables) = 0"/> + + <!-- It is assumed there is no support for overloaded specs + (there is no spec with more than one clause) --> + <xsl:if test="count($clause/guard) > 0 or count($type) > 0"> + <fo:block> + <xsl:text>Types:</xsl:text> + </fo:block> + <fo:list-block xsl:use-attribute-sets="type-listblock"> + <xsl:choose> + <xsl:when test="$output_subtypes"> + <xsl:call-template name="subtype"> + <xsl:with-param name="subtype" select="$clause/guard/subtype"/> + <xsl:with-param name="type_desc" select="$type_desc"/> + <xsl:with-param name="local_types" select="$local_types"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="type_variables"> + <xsl:with-param name="type_variables" select="$type_variables"/> + <xsl:with-param name="type_desc" select="$type_desc"/> + <xsl:with-param name="local_types" select="$local_types"/> + <xsl:with-param name="fname" select="$name"/> + <xsl:with-param name="arity" select="$arity"/> + </xsl:call-template> + + </xsl:otherwise> + </xsl:choose> + + <xsl:call-template name="local_type"> <xsl:with-param name="type_desc" select="$type_desc"/> + <xsl:with-param name="local_types" select="$local_types"/> </xsl:call-template> - </xsl:if> - </xsl:for-each> + </fo:list-block> + </xsl:if> </xsl:template> - <xsl:template match="head"> - <fo:block xsl:use-attribute-sets="function-name"> - <xsl:apply-templates/> - </fo:block> - </xsl:template> + <!-- Handle <type variable="..." name_i="..."/> --> + <xsl:template name="type_variables"> + <xsl:param name="type_variables"/> + <xsl:param name="type_desc"/> + <xsl:param name="local_types"/> + <xsl:param name="fname"/> + <xsl:param name="arity"/> + + <xsl:variable name="names" select="../name[string-length(@arity) > 0]"/> + <xsl:for-each select="$type_variables"> + <xsl:variable name="name_i"> + <xsl:choose> + <xsl:when test="string-length(@name_i) > 0"> + <xsl:value-of select="@name_i"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="count($names)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="spec0"> + <xsl:for-each select="$names[position() = $name_i]"> + <xsl:call-template name="find_spec"/> + </xsl:for-each> + </xsl:variable> + <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/> + <xsl:variable name="clause" select="$spec/contract/clause"/> + <xsl:variable name="variable" select="@variable"/> + <xsl:variable name="subtype" + select="$clause/guard/subtype[typename = $variable]"/> + + <xsl:if test="count($subtype) = 0"> + <xsl:call-template name="err"> + <xsl:with-param name="f" select="ancestor::erlref/module"/> + <xsl:with-param name="n" select="$fname"/> + <xsl:with-param name="a" select="$arity"/> + <xsl:with-param name="s">unknown type variable <xsl:value-of select="$variable"/> + </xsl:with-param> + </xsl:call-template> + </xsl:if> - <xsl:template name="guard"> - <fo:block> - <xsl:text>Types:</xsl:text> - </fo:block> - <fo:list-block xsl:use-attribute-sets="type-listblock"> <xsl:call-template name="subtype"> - <xsl:with-param name="subtype" select="$guard/subtype"/> - <xsl:with-param name="type_desc" select="$type_desc"/> + <xsl:with-param name="subtype" select="$subtype"/> + <xsl:with-param name="type_desc" select="$type_desc"/> </xsl:call-template> - </fo:list-block> + </xsl:for-each> </xsl:template> + <!-- Substituted + <fo:block xsl:use-attribute-sets="function-name"> + for + <fo:block font-weight="bold"> + to get proper indentation (a monospace font) + --> <xsl:template name="subtype"> <xsl:param name="subtype"/> <xsl:param name="type_desc"/> + <xsl:for-each select="$subtype"> <xsl:variable name="tname" select="typename"/> - <xsl:variable name="tdesc" select="$type_desc[@name = $tname]"/> <fo:list-item xsl:use-attribute-sets="type-listitem"> <fo:list-item-label end-indent="label-end()"> <fo:block> </fo:block> </fo:list-item-label> <fo:list-item-body start-indent="body-start()" format="justify"> - <fo:block font-weight="bold"> - <xsl:apply-templates select="string"/> + <fo:block xsl:use-attribute-sets="function-name"> + <xsl:apply-templates select="string"/> </fo:block> </fo:list-item-body> </fo:list-item> - <xsl:apply-templates select="$type_desc[@name = $tname]"/> + <xsl:apply-templates select="$type_desc[@variable = $tname]"/> + </xsl:for-each> + </xsl:template> + + <xsl:template name="local_type"> + <xsl:param name="type_desc"/> + <xsl:param name="local_types"/> + + <xsl:for-each select="$local_types"> + <fo:list-item xsl:use-attribute-sets="type-listitem"> + <fo:list-item-label end-indent="label-end()"> + <fo:block> + </fo:block> + </fo:list-item-label> + <fo:list-item-body start-indent="body-start()" format="justify"> + <!-- <fo:block font-weight="bold"> + (use function-name in "typehead" instead) --> + <xsl:call-template name="type_name"> + <xsl:with-param name="mode" select="'local_type'"/> + </xsl:call-template> + <!-- </fo:block> --> + </fo:list-item-body> + </fo:list-item> + <xsl:variable name="tname" select="@name"/> + <xsl:variable name="tnvars" select="@n_vars"/> + <xsl:apply-templates select= + "$type_desc[@name = $tname + and (@n_vars = $tnvars + or string-length(@n_vars) = 0 and + string-length($tnvars) = 0)]"/> </xsl:for-each> </xsl:template> @@ -182,6 +302,53 @@ <xsl:apply-templates select="desc"/> </xsl:template> + <xsl:template name="type_name"> + <xsl:param name="mode"/> <!-- '' if <datatype> --> + <xsl:variable name="curModule" select="ancestor::erlref/module"/> + <xsl:variable name="mod" select="@mod"/> + <xsl:variable name="name" select="@name"/> + <xsl:variable name="n_vars" select="@n_vars"/> + + <xsl:choose> + <xsl:when test="string-length($name) > 0"> + <xsl:variable name="type" select= + "$i/specs/module[@name=$curModule]/type + [name=$name + and (string-length($n_vars) = 0 or n_vars = $n_vars) + and (string-length($mod) = 0 or module = $mod)]"/> + + <xsl:if test="count($type) != 1"> + <xsl:variable name="why"> + <xsl:choose> + <xsl:when test="count($type) > 1">ambiguous type</xsl:when> + <xsl:when test="count($type) = 0">unknown type</xsl:when> + </xsl:choose> + </xsl:variable> + <xsl:call-template name="err"> + <xsl:with-param name="f" select="$curModule"/> + <xsl:with-param name="m" select="$mod"/> + <xsl:with-param name="n" select="$name"/> + <xsl:with-param name="a" select="$n_vars"/> + <xsl:with-param name="s" select="$why"/> + </xsl:call-template> + </xsl:if> + <xsl:choose> + <xsl:when test="$mode = ''"> + <xsl:apply-templates select="$type/typedecl"/> + </xsl:when> + <xsl:when test="$mode = 'local_type'"> + <xsl:apply-templates select="$type/typedecl" mode="local_type"/> + </xsl:when> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <fo:inline font-weight="bold" xsl:use-attribute-sets="type-listitem"> + <xsl:value-of select="."/> + </fo:inline> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <!-- Like <head>... --> <xsl:template match="typehead"> <fo:block xsl:use-attribute-sets="function-name"> @@ -189,6 +356,20 @@ </fo:block> </xsl:template> + <!-- Substituted + <fo:block xsl:use-attribute-sets="function-name"> + for + <fo:block font-weight="bold"> + to get proper indentation (a monospace font) + --> + + <xsl:template match="typehead" mode="local_type"> + <fo:block xsl:use-attribute-sets="function-name"> + <xsl:apply-templates/> + </fo:block> + </xsl:template> + + <!-- Not used right now --> <!-- Like <guard>, except "Types:"... --> <xsl:template match="local_defs"> <fo:list-block xsl:use-attribute-sets="type-listblock"> @@ -211,108 +392,82 @@ </fo:list-item> </xsl:template> - <xsl:template name="type_name"> - <xsl:variable name="curModule" select="ancestor::erlref/module"/> - <xsl:variable name="mod" select="@mod"/> - <xsl:variable name="name" select="@name"/> - <xsl:variable name="n_vars"> - <xsl:choose> - <xsl:when test="string-length(@n_vars) > 0"> - <xsl:value-of select="@n_vars"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="0"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:choose> - <xsl:when test="string-length($name) > 0"> - <xsl:variable name="type" select= - "$i/specs/module[@name=$curModule]/type - [name=$name and n_vars=$n_vars - and (string-length($mod) = 0 or module = $mod)]"/> - - <xsl:if test="count($type) != 1"> - <xsl:call-template name="err"> - <xsl:with-param name="m" select="$mod"/> - <xsl:with-param name="n" select="$name"/> - <xsl:with-param name="a" select="$n_vars"/> - <xsl:with-param name="s">unknown type</xsl:with-param> - </xsl:call-template> - </xsl:if> - <xsl:apply-templates select="$type/typedecl"/> - </xsl:when> - <xsl:otherwise> - <fo:inline font-weight="bold" xsl:use-attribute-sets="type-listitem"> - <xsl:value-of select="."/> - </fo:inline> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - <!-- Used both in <datatype> and in <func>! --> <xsl:template match="anno"> <xsl:variable name="curModule" select="ancestor::erlref/module"/> <xsl:variable name="anno" select="normalize-space(text())"/> <xsl:variable name="namespec" - select="ancestor::desc/preceding-sibling::name"/> + select="ancestor::type_desc/preceding-sibling::name + | ancestor::desc/preceding-sibling::name"/> <xsl:if test="count($namespec) = 0 and string-length($specs_file) > 0"> <xsl:call-template name="err"> - <xsl:with-param name="s">cannot find 'name' (<xsl:value-of select="$anno"/>) + <xsl:with-param name="f" select="$curModule"/> + <xsl:with-param name="s">cannot find tag 'name' (anno <xsl:value-of select="$anno"/>) </xsl:with-param> </xsl:call-template> </xsl:if> - <xsl:variable name="mod" select="$namespec/@mod"/> - <xsl:variable name="name" select="$namespec/@name"/> - <xsl:variable name="arity" select="$namespec/@arity"/> - <xsl:variable name="clause" select="$namespec/@clause"/> - <xsl:variable name="tmp_n_vars" select="$namespec/@n_vars"/> - <xsl:variable name="n_vars"> - <xsl:choose> - <xsl:when test="string-length($tmp_n_vars) > 0"> - <xsl:value-of select="$tmp_n_vars"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="0"/> - </xsl:otherwise> - </xsl:choose> + <!-- Search "local types" as well --> + <xsl:variable name="local_types" + select="ancestor::desc/preceding-sibling::type + [string-length(@name) > 0]"/> + <xsl:variable name="has_anno_in_local_type"> + <xsl:for-each select="$local_types"> + <xsl:call-template name="anno_name"> + <xsl:with-param name="curModule" select="$curModule"/> + <xsl:with-param name="anno" select="$anno"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:variable name="has_anno"> + <xsl:for-each select="$namespec"> + <xsl:call-template name="anno_name"> + <xsl:with-param name="curModule" select="$curModule"/> + <xsl:with-param name="anno" select="$anno"/> + </xsl:call-template> + </xsl:for-each> </xsl:variable> + + <xsl:if test="$has_anno = '' and $has_anno_in_local_type = ''"> + <xsl:call-template name="err"> + <xsl:with-param name="f" select="$curModule"/> + <xsl:with-param name="m" select="$namespec/@mod"/> + <xsl:with-param name="n" select="$namespec/@name"/> + <xsl:with-param name="a" select="'-'"/> + <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/> + </xsl:with-param> + </xsl:call-template> + </xsl:if> + <xsl:value-of select="$anno"/> + </xsl:template> + + <xsl:template name="anno_name"> + <xsl:param name="curModule"/> + <xsl:param name="anno"/> + <xsl:variable name="mod" select="@mod"/> + <xsl:variable name="name" select="@name"/> + <xsl:variable name="arity" select="@arity"/> + <xsl:variable name="n_vars" select="@n_vars"/> + <xsl:variable name="clause_i" select="@clause_i"/> + <xsl:variable name="spec0" select= "$i/specs/module[@name=$curModule]/spec [name=$name and arity=$arity and (string-length($mod) = 0 or module = $mod)]"/> <xsl:variable name="spec_annos" select= - "$spec0[string-length($clause) = 0 - or position() = $clause]/anno[.=$anno]"/> + "$spec0[string-length($clause_i) = 0 + or position() = $clause_i]/anno[.=$anno]"/> <xsl:variable name="type_annos" select= "$i/specs/module[@name=$curModule]/type - [name=$name and n_vars=$n_vars + [name=$name + and (string-length($n_vars) = 0 or n_vars=$n_vars) and (string-length($mod) = 0 or module = $mod)]/anno[.=$anno]"/> - - <xsl:if test="count($spec_annos) = 0 - and count($type_annos) = 0 - and string-length($specs_file) > 0"> - <xsl:variable name="n"> - <xsl:choose> - <xsl:when test="string-length($arity) = 0"> - <xsl:value-of select="$n_vars"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="$arity"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - <xsl:call-template name="err"> - <xsl:with-param name="m" select="$mod"/> - <xsl:with-param name="n" select="$name"/> - <xsl:with-param name="a" select="$n"/> - <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/> - </xsl:with-param> - </xsl:call-template> + <xsl:if test="count($spec_annos) != 0 + or count($type_annos) != 0 + or string-length($specs_file) = 0"> + <xsl:value-of select="true()"/> </xsl:if> - <xsl:value-of select="$anno"/> </xsl:template> <!-- Used for indentation of formatted types and specs --> @@ -1227,6 +1382,9 @@ <xsl:param name="partnum"/> <xsl:apply-templates select="name"/> + <xsl:apply-templates + select="name[string-length(@arity) > 0 and position()=last()]" + mode="types"/> <xsl:apply-templates select="fsummary|type|desc"> <xsl:with-param name="partnum" select="$partnum"/> @@ -1245,6 +1403,11 @@ <xsl:when test="ancestor::datatype"> <xsl:call-template name="type_name"/> </xsl:when> + <xsl:when test="string-length(text()) = 0 and ancestor::erlref"> + <xsl:message terminate="yes"> + Error <xsl:value-of select="@name"/>: arity is mandatory when referring to specifications! + </xsl:message> + </xsl:when> <xsl:otherwise> <fo:block xsl:use-attribute-sets="function-name"> <xsl:call-template name="name"> @@ -1276,15 +1439,20 @@ <xsl:template match="type"> <xsl:param name="partnum"/> - <fo:block> - <xsl:text>Types:</xsl:text> - </fo:block> + <!-- The case where @name != 0 is taken care of in "type_name" --> + <xsl:if test="string-length(@name) = 0 and string-length(@variable) = 0"> - <fo:list-block xsl:use-attribute-sets="type-listblock"> - <xsl:apply-templates> - <xsl:with-param name="partnum" select="$partnum"/> - </xsl:apply-templates> - </fo:list-block> + <fo:block> + <xsl:text>Types:</xsl:text> + </fo:block> + + <fo:list-block xsl:use-attribute-sets="type-listblock"> + <xsl:apply-templates> + <xsl:with-param name="partnum" select="$partnum"/> + </xsl:apply-templates> + </fo:list-block> + + </xsl:if> </xsl:template> @@ -1431,6 +1599,7 @@ </xsl:template> + <!-- Does not look at @n_vars --> <xsl:template match="seealso"> <fo:inline font-style="italic"> <xsl:apply-templates/> |