summaryrefslogtreecommitdiffstats
path: root/header.FDL
blob: 264a1ff342167dc66938f49a0eed4c8c9ec9aee1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of this
** file.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

d by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ +/*! \page langhowto Internationalization + +

Support for multiple languages

+ +Doxygen has support for multiple languages. This means +that the text fragments that doxygen generates can changed into languages +other than English (the default) at configuration time. +

+Currently, $numlang languages are supported (sorted alphabetically): +$languages. + +The table of information related to the supported languages follows. +It is sorted by language alphabetically. The Status column +was generated from sources and shows approximately the last version +when the translator was updated. +

+ +$information_table +Have a look at doxygen/doc/translator.txt for more details. +

+ +Most people on the list have indicated that they were also busy +doing other things, so if you want to help to speed things up please +let them (or me) know. + +If you want to add support for a language that is not yet listed +please see the next section. + +

Adding a new language to doxygen

+ +This short HOWTO explains how to add support for a new language to Doxygen: + +Just follow these steps: +
    +
  1. Tell me for which language you want to add support. If no one else + is already working on support for that language, you will be + assigned as the maintainer for the language. +
  2. Create a copy of translator_en.h and name it + translator_.h + I'll use xx in the rest of this document. +
  3. Edit language.cpp: + Add a +\verbatim +#include +\endverbatim + in setTranslator() add +\verbatim + else if (L_EQUAL("your_language_name")) + { + theTranslator = new TranslatorYourLanguage; + } +\endverbatim + after the if { ... } +
  4. Edit libdoxygen.pro.in and add \c translator_xx.h to + the \c HEADERS line in the file doxygen.pro. +
  5. Edit translator_xx.h: + +
  6. Run configure and make again from the root of the distribution, + in order to regenerated the Makefiles. +
  7. Now you can use OUTPUT_LANGUAGE = your_language_name + in the config file to generate output in your language. +
  8. Send translator_xx.h to me so I can add it to doxygen. +
+ +

Maintaining a language

+ +As new versions of doxygen appear, new sentences will be +added to the Translator interface class. Of course these need to be translated +as well (otherwise doxygen wouldn't even compile!). + +Waiting until all language maintainers have translated these new sentences +and sent the results would not be very practical for me. + +Instead, a new class TranslatorAdapter_x_y_z will be added to +translator_adapter.h (here x,y, and z correspond to the current +version of doxygen). And all translators that previous derived from +Translator will now derive from this adapter class. + +The Adapter class contains the new sentences with +default translations using the English translator (which is always up to date). +Instead of deriving your TranslatorXX class directly from Translator it will +derive from the intermediate class TranslatorAdapter_x_y_z. + +Thus, if a translator class inherits from a adapter class +maintenance is needed. By looking at the adapter class itself (and its base +classes) you can easily see which methods need to be updated. + +To update a language simply make your translator class derive from +the abstract class Translator and provide translations for the methods that +were previously provided by the adapter class (and its base classes). + +*/ + diff --git a/doc/translator.bat b/doc/translator.bat new file mode 100644 index 0000000..fc12581 --- /dev/null +++ b/doc/translator.bat @@ -0,0 +1,4 @@ +:start +call perl -w translator.pl +pause +goto start \ No newline at end of file diff --git a/doc/translator.pl b/doc/translator.pl new file mode 100644 index 0000000..f5b889e --- /dev/null +++ b/doc/translator.pl @@ -0,0 +1,752 @@ +#! /usr/bin/perl -w +# -*- mode: perl; mode: fold -*- + +# This is a Perl script for Doxygen developers. +# Its main purpose is to extract the information from sources +# related to internationalization (the translator classes). +# +# Petr Prikryl (prikrylp@skil.cz) +# History: +# -------- +# 2001/04/27 +# - First version of the script. +# +# 2002/05/02 +# - Update to accept updateNeededMessage() in the Translator class. +# - First version that generates doc/language.doc. +# +################################################################ + +require 5.005; +use strict; +use Carp; + +# Global variables +# +my $doxygenrootdir = ".."; +my $srcdir = "$doxygenrootdir/src"; +my $docdir = "$doxygenrootdir/doc"; + +# Names of the output files. +# +my $ftxt = "translator_report.txt"; +my $fdoc = "language.doc"; + + +################################################################ +# GetPureVirtual returns a hash of pure virtual method prototypes +# in a hash where the key is the method prototype, and the value +# is 1. The input argument is the full name of the source file. +# +sub GetPureVirtualFrom ##{{{ +{ + my $fin = shift; # Get the file name. + + # Let's open the file and read it into a single string. + # + open(FIN, "< $fin") or die "\nError when open < $fin: $!"; + my @content = ; + close FIN; + my $cont = join("", @content); + + # Remove comments and empty lines. + # + $cont =~ s{\s*//.*$}{}mg; # remove one-line comments + while ($cont =~ s{/\*.+?\*/}{}sg ) {} # remove C comments + $cont =~ s{\n\s*\n}{\n}sg; # remove empty lines + + # Remove the beginning up to the first virtual method. + # Remove also the text behind the class. + # + $cont =~ s/^.*?virtual/virtual/s; + $cont =~ s/\n\};.*$//s; + + # Erase anything between "=0;" and "virtual". Only the pure + # virtual methods will remain. Remove also the text behind + # the last "= 0;" + # + $cont =~ s{(=\s*0\s*;).*?(virtual)}{$1 $2}sg; + $cont =~ s{^(.+=\s*0\s*;).*?$}{$1}s; + + # Remove the empty implementation of the updateNeededMessage() + # method which is to be implemented by adapters only, not by + # translators. + # + $cont =~ s{\s*virtual + \s+QCString + \s+updateNeededMessage\(\) + \s+\{\s*return\s+"";\s*\} + } + {}xs; + + # Replace all consequent white spaces (including \n) by a single + # space. Trim also the leading and the trailing space. + # + $cont =~ s{\s+}{ }sg; + $cont =~ s{^\s+}{}s; + $cont =~ s{\s+$}{}s; + + # Split the result to the lines again. Remove the "= 0;". + # + $cont =~ s{\s*=\s*0\s*;\s*}{\n}sg; + + # Remove the keyword "virtual" because the derived classes + # may not use it. + # + $cont =~ s{^virtual\s+}{}mg; + + # Split the string into array of lines and fill the output hash. + # + my %result = (); + + foreach (split(/\n/, $cont)) { + $result{$_} = 1; + } + + return %result; +} +##}}} + + +################################################################ +# GetInfoFrom returns the list of information related to the +# parsed source file. The input argument is the name of the +# translator_xx.h file including path. +# +# The output list contains the following items: +# - class identifier +# - base class identifier +# - method prototypes (each in a separate item) +# +sub GetInfoFrom ##{{{ +{ + # Get the file name. + # + my $fin = shift; + + # Let's open the file and read it into a single string. + # + open(FIN, "< $fin") or die "\nError when open < $fin: $!"; + my @content = ; + close FIN; + my $cont = join("", @content); + + # Remove comments and empty lines. + # + $cont =~ s{\s*//.*$}{}mg; # remove one-line comments + $cont =~ s{/\*.+?\*/}{}sg; # remove C comments + $cont =~ s{\n\s*\n}{\n}sg; # remove empty lines + + # Extract the class and base class identifiers. Remove the + # opening curly brace. Remove also the first "public:" + # Put the class and the base class into the output list. + # + $cont =~ s{^.*class\s+(Translator\w+)[^:]*: + \s*public\s+(\w+)\b.*?\{\s* + (public\s*:\s+)? + } + {}sx; + + @content = ($1, $2); + + # Cut the things after the class. + # + $cont =~ s{\}\s*;\s*#endif\s*$}{}s; + + # Remove the "virtual" keyword, because some the derived class + # is not forced to use it. + # + $cont =~ s{^\s*virtual\s+}{}mg; + + # Remove all strings from lines. + # + $cont =~ s{".*?"}{}mg; + + # Remove all bodies of methods; + # + while ($cont =~ s/{[^{}]+?}//sg) {} + + # Remove all private methods, i.e. from "private:" to "public:" + # included. Later, remove also all from "private:" to the end. + # + $cont =~ s{private\s*:.*?public\s*:}{}sg; + $cont =~ s{private\s*:.*$}{}s; + + # Some of the translators use conditional compilation where + # the branches define the body of the method twice. Remove + # the ifdef/endif block content. + # + $cont =~ s{#ifdef.*?#endif}{}sg; + + # Now the string should containt only method prototypes. + # Let's unify their format by removing all spaces that + # are not necessary. Then let's put all of them on separate + # lines (one protototype -- one line; no empty lines). + # + $cont =~ s{\s+}{ }sg; + $cont =~ s{^\s+}{}s; + $cont =~ s{\s+$}{}s; + + $cont =~ s{\)\s*}{)\n}g; + + # Split the string and add it to the ouptut list. + # + @content = (@content, split(/\n/, $cont)); + return @content; +} +##}}} + + +################################################################ +# GenerateLanguageDoc takes document templates and code sources +# generates the content as expected in the language.doc file (the +# part of the Doxygen documentation), and returns the result as a +# string. +# +sub GenerateLanguageDoc ##{{{ +{ + # Get the references to the hash of class/base class. + # + my $rcb = shift; + + # Define templates for HTML table parts of the documentation. #{{{ + # + my $htmlTableHead = <<'xxxTABLE_HEADxxx'; +\htmlonly + + + + +
+ + + + + + + +xxxTABLE_HEADxxx + + my $htmlTableRow = <<'xxxTABLE_ROWxxx'; + + + + + + +xxxTABLE_ROWxxx + + my $htmlTableFoot = <<'xxxTABLE_FOOTxxx'; +
Language Maintainer Contact address + (remove the NOSPAM.) Status
$lang$maintainer$email$status
+
+\endhtmlonly +xxxTABLE_FOOTxxx + ##}}} + + # Define templates for LaTeX table parts of the documentation. #{{{ + # + my $latexTableHead = <<'xxxTABLE_HEADxxx'; +\latexonly +\begin{tabular}{|l|l|l|l|} + \hline + {\bf Language} & {\bf Maintainer} & {Contact address} & {Status} \\ +xxxTABLE_HEADxxx + + my $latexTableRow = <<'xxxTABLE_ROWxxx'; + $lang & $maintainer & {\tt $email} & $status \\ +xxxTABLE_ROWxxx + + my $latexTableFoot = <<'xxxTABLE_FOOTxxx'; + \hline +\end{tabular} +\endlatexonly +xxxTABLE_FOOTxxx + ##}}} + + # Read the template of the documentation, and join the content + # to a single string. #{{{ + # + my $fin = "$docdir/language.tpl"; + open(FIN, "< $fin") or die "\nError when open < $fin: $!"; + my @content = ; + close FIN; + + my $output = join("", @content); + ##}}} + + # Make and substitute the list of supported languages and their + # number. #{{{ + # + my @languages = sort grep { s{^Translator}{} } keys %{$rcb}; + + my $numlang = @languages; + + $output =~ s{\$numlang}{$numlang}; + + my $languages = join(", ", @languages); + $languages =~ s{((\w+,\s){5})}{$1\n}g; + $languages =~ s{Brazilian}{Brazilian Portuguese}; + $languages =~ s{(,\s+)(\w+)$}{$1and $2}s; + + $output =~ s{\$languages}{$languages}; + ##}}} + + # Create the hash of languages with the initial info. #{{{ + # + my %language = (); + + foreach (@languages) { + $language{$_} = $$rcb{"Translator$_"} . "unknown: unknown"; + } + ##}}} + + # Read the information related to maintainers into the + # string using suitable separators -- one line, one language. #{{{ + # + $fin = "$docdir/maintainers.txt"; + open(FIN, "< $fin") or die "\nError when open < $fin: $!"; + my @maintainers = ; + close FIN; + + my $maintainers = join("", @maintainers); + + # Trim the spaces on the lines. Strip the comment lines that + # start with % sign. + # + $maintainers =~ s{^[ \t]+}{}mg; + $maintainers =~ s{[ \t]+$}{}mg; + + $maintainers =~ s{^%.*$}{}mg; + + # Join the information for one language into one line, + # and remove empty lines. + # + $maintainers =~ s{\b\n\b}{}sg; + $maintainers =~ s{\n{2,}}{\n}sg; + $maintainers =~ s{^\n+}{}s; + $maintainers =~ s{\n+$}{}s; + ##}}} + + # Split the string back to the list, and update the information + # in the hash with information for languages. #{{{ + # + foreach my $line (sort split(/\n/, $maintainers)) { + + # Split the line for one language to separate lines for + # the language and one or more maintainers. + # + my @info = split(//, $line); + + my $lang = shift @info; + + # Ensure that the language starts with uppercase and + # continues with lowercase. + # + $lang =~ s{^(\w)(\w+)}{\U$1\L$2\E}; + + # Add information to the %language hash. If the language + # was not defined in sources, add the question mark to the + # language identifier. + # + if (defined $language{$lang}) { + $language{$lang} = $$rcb{"Translator$lang"} . '' + . join("", @info); + } + else { + $lang .= " (?)"; + $language{$lang} = "unknown" . join("", @info); + } + } + ##}}} + + # Now, the %language hash contains all the information needed for + # generating the tables (HTML and LaTeX). Define string variables + # for each of the tables, and initialize them. #{{{ + # + my $tableHTML = $htmlTableHead; + my $tableLATEX = $latexTableHead; + ##}}} + + # Loop through sorted keys for the languages, parse the + # information, and add it to the tables. #{{{ + # + foreach my $lang (sort keys %language) { + + # Read the line with info for the language and separate + # the information of status. #{{{ + # + my @list = split(//, $language{$lang}); + my $status = shift @list; + + my $i = $status =~ s{^Translator$}{up-to-date}; + + if ($i == 0) { + $i = $status =~ s{^TranslatorAdapter_(\d)_(\d)_(\d)} + {$1.$2.$3}x; + } + + if ($i == 0) { $status = '?'; } + + ##}}} + + # Split the rest of the list (should be a single item) into + # the list with one or more maintainers -- one line, one + # maintainer. #{{{ + # + my $rest = shift @list; + @list = split(//, $rest); + ##}}} + + # In HTML table, maintainer names are placed in the same + # cell. Also their e-mails are placed in a single cell. + # Extract the string with concatenated names and the string + # with concatenated e-mails. Add the row to the HTML + # table. #{{{ + # + my $name = ''; + my $email = ''; + + foreach my $maintainer (@list) { + + if ($name ne '') { $name .= '
'; } + if ($email ne '') { $email .= '
'; } + + $maintainer =~ m{^\s*(.+?)\s*:\s*(.+?)\s*$}; + + $name .= $1; + $email .= $2; + } + + # Prepare the HTML row template, modify it, and add the + # result to the HTML table. + # + my $item = $htmlTableRow; + + $item =~ s{\$lang}{$lang}; + $item =~ s{\$maintainer}{$name}; + $item =~ s{\$email}{$email}; + $item =~ s{\$status}{$status}; + + $tableHTML .= $item; + + ##}}} + + # For LaTeX, more maintainers for the same language are + # placed on separate rows in the table. The line separator + # in the table is placed explicitly above the first + # maintainer. Add rows for all maintainers to the LaTeX + # table. #{{{ + # + # Prepare the LATEX row template, modify it, and add the + # result to the LATEX table. + # + $item = $latexTableRow; + + my $first = shift @list; # the first maintainer. + $first =~ m{^\s*(.+?)\s*:\s*(.+?)\s*$}; + + $name = $1; + $email = $2; + + $item =~ s{\$lang}{$lang}; + $item =~ s{\$maintainer}{$name}; + $item =~ s{\$email}{$email}; + $item =~ s{\$status}{$status}; + + $tableLATEX .= " \\hline\n" . $item; + + # List the other maintainers for the language. Do not set + # lang and status for them. + # + while (@list) { + my $next = shift @list; + $next =~ m{^\s*(.+?)\s*:\s*(.+?)\s*$}; + + my $name = $1; + my $email = $2; + my $item = $latexTableRow; + + $item =~ s{\$lang}{}; + $item =~ s{\$maintainer}{$name}; + $item =~ s{\$email}{$email}; + $item =~ s{\$status}{}; + + $tableLATEX .= $item; + } + ##}}} + } + ##}}} + + # Finish the tables, and substitute the mark in the doc + # template by the contatenation of the tables. Add NOSPAM to + # email addresses in the HTML table. Replace the special + # character sequences. #{{{ + # + $tableHTML .= $htmlTableFoot; + $tableLATEX .= $latexTableFoot; + + $tableHTML =~ s{@}{\@NOSPAM.}sg; + $tableHTML =~ s{ř}{ř}sg; + + $tableLATEX =~ s/ř/\\v{r}/sg; + $tableLATEX =~ s/á/\\'{a}/sg; + $tableLATEX =~ s/ä/\\"{a}/sg; + $tableLATEX =~ s/ö/\\"{o}/sg; + $tableLATEX =~ s/_/\\_/sg; + + $output =~ s{\$information_table}{$tableHTML$tableLATEX}; + ##}}} + + # Replace the introduction notice in the output. #{{{ + # + $output =~ s{.+?} +{Warning: this file was generated from the language.tpl template + * Do not edit this file. Edit the template!}sx; + ##}}} + + # Return the content of the generated output file. + # + return $output; +} +##}}} + + +################################################################ +# Body +# +{ + # The translator base class must be present. Exit otherwise. #{{{ + # + if (!-f "$srcdir/translator.h") + { + print STDERR "\n\nThe translator.h not found in $srcdir.\n\n\a"; + exit 1; + } + ##}}} + + # Find all translator_xx.h files. #{{{ + # + my @entries = (); # init + + opendir DIR, $srcdir or confess "opendir error for $srcdir: $!"; + foreach (readdir(DIR)) { if (!/^\./) { push @entries, $_; } } + closedir DIR; # ignore names with dot at the beginning + + my @files = sort + grep { -f "$srcdir/$_" && m{^translator_..\.h$}i } + @entries; + ##}}} + + # Get only the pure virtual methods from the Translator class + # into a hash structure for later testing present/not present. + # + my %required = GetPureVirtualFrom("$srcdir/translator.h"); + + # Collect base classes of translators the hash. + # + my %cb = (); + + # The details for translators will be collected into the output + # string. + # + my $output = ''; + + # Loop through all translator files. Extract the implemented + # virtual methods and compare it with the requirements. Prepare + # the output. + # + foreach (@files) { + + # Get the information from the sources. Remember the base + # class for each of the classes. #{{{ + # + my @info = GetInfoFrom("$srcdir/$_"); + + my $class = shift @info; + my $base = shift @info; + + $cb{$class} = $base; + ##}}} + + # Set the value of the required methods to 1 (true). Let + # this indicate that the method was not defined in the + # translator class. + # + foreach (keys %required) { $required{$_} = 1; } + + # Loop through all items and compare the prototypes. Mark + # the implemented method and collect the old ones. #{{{ + # + my @old_methods = (); + + foreach my $method (@info) { + if (defined $required{$method}) { $required{$method} = 0; } + else {push(@old_methods, $method); } + } + ##}}} + + # Loop through the required hash and collect the missing + # (new) methods. Do this only when it derives from + # Translator or TranslatorAdapter classes. #{{{ + # + my @missing_methods = (); + + if ($base =~ m/^Translator(Adapter.*)?$/) { + foreach (keys %required) { + if ($required{$_}) { push(@missing_methods, $_); } + } + } + ##}}} + + # The detailed output will be produced only when it is + # needed. #{{{ + # + if (@old_methods || @missing_methods + || $base !~ m/^Translator(Adapter.*)?$/) { + + $output .= "\n\n\n"; + $output .= $class . " ($base)\n" . '-' x length($class) . "\n"; + + if ($base !~ m/^Translator(Adapter.*)?$/) { + $output .= "\nThis is the unusual implementation of the " + . "translator. Its class is derived\n" + . "from the $base base class. The usual translator" + . "class derives\n" + . "or from the Translator class or from some " + . "TranslatorAdapter_x_x_x classes.\n" + . "Because of that, nothing can be guessed about " + . "missing methods.\n"; + } + + if (@missing_methods) { + $output .= "\nMissing methods (should be implemented):\n\n"; + foreach (@missing_methods) { $output .= " $_\n"; } + } + + if (@old_methods) { + $output .= "\nObsolete methods (should be removed):\n\n"; + foreach (sort @old_methods) { $output .= " $_\n"; } + } + } + ##}}} + } + + + # Generate the textual output file. + # + my $fout = "$docdir/$ftxt"; + + # Open it first. + # + open(FOUT, "> $fout") or die "\nError when open > $fout: $!"; + + # List the supported languages. #{{{ + # + my @all_translators = keys %cb; + + print FOUT "Doxygen supports the following (" . @all_translators + . ") languages (sorted alphabetically):\n\n"; + + foreach (sort grep { s/^Translator(\w+)\b.*$/$1/ } @all_translators) { + print FOUT " $_\n"; + } + ##}}} + + # If there are up-to-date translators, list them. #{{{ + # + my @list = sort grep { $cb{$_} =~ m/^Translator$/ } keys %cb; + + if (@list) { + print FOUT "\n" .'-' x 70 . "\n"; + print FOUT "The following translator classes are up-to-date " + . "(sorted alphabetically).\n" + . "This means that they derive from the Translator class. " + . "However, there still\n" + . "may be some details listed below " + . "for them. Please, check it.\n\n"; + + foreach (@list) { print FOUT " $_\n"; } + } + ##}}} + + # If there are obsolete translators, list them. #{{{ + # + @list = sort grep { $cb{$_} =~ m/^TranslatorAdapter/ } keys %cb; + + if (@list) { + print FOUT "\n" .'-' x 70 . "\n"; + print FOUT "The following translator classes are obsolete " + . "(sorted alphabetically).\n" + . "This means that they derive from some of " + . "the adapter classes.\n\n"; + + foreach (@list) { print FOUT " $_\t($cb{$_})\n"; } + } + ##}}} + + # If there are other translators, list them. #{{{ + # + @list = sort + grep { $cb{$_} !~ m/^Translator$/ } + grep { $cb{$_} !~ m/^TranslatorAdapter/ } + keys %cb; + + if (@list) { + print FOUT "\n" .'-' x 70 . "\n"; + print FOUT "The following translator classes are somehow different\n" + . "(sorted alphabetically). This means that they " + . "do not derive from\n" + . "the Translator class, nor from some of the adapter classes.\n\n"; + + foreach (@list) { print FOUT " $_\t($cb{$_})\n"; } + } + ##}}} + + # List the methods that are expected to be implemented. #{{{ + print FOUT "\n\n" .'-' x 70 . "\n"; + print FOUT "Localized translators are expected to implement " + . "the following methods\n" + . "(prototypes sorted aplhabetically):\n\n"; + + foreach (sort keys(%required)) { + print FOUT "$_\n"; + } + ##}}} + + # If there are some details for the translators, show them. #{{{ + # + if ($output !~ m/^\s*$/) { + print FOUT "\n\n" .'-' x 70 . "\n"; + print FOUT "Details related to specific translator classes follows.\n" + . "Notice that the prototypes are recognized only when they\n" + . "are the same as in the Translator class."; + + print FOUT $output . "\n"; + } + ##}}} + + # Close the output file + # + close FOUT; + + # Generate the language.doc file. + # + $fout = "$docdir/$fdoc"; + + # Open it first for the output. + # + open(FOUT, "> $fout") or die "\nError when open > $fout: $!"; + + print FOUT GenerateLanguageDoc(\%cb); + + # Close the output file + # + close FOUT; + + + exit 0; +} +# end of body +################################################################ + diff --git a/src/Makefile.in b/src/Makefile.in index 682caf7..9ce2734 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,6 +1,6 @@ # -# $Id$ +# # # Copyright (C) 1997-2001 by Dimitri van Heesch. # diff --git a/src/classdef.cpp b/src/classdef.cpp index 58b0e65..c3219d6 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -49,76 +49,73 @@ ClassDef::ClassDef( const char *lref,const char *fName) : Definition(defFileName,defLine,removeRedundantWhiteSpace(nm)) { - //name=n; - - compType=ct; + m_compType=ct; QCString compoundName=compoundTypeString(); if (fName) { - fileName=stripExtension(fName); + m_fileName=stripExtension(fName); } else { - fileName=compoundName+nm; + m_fileName=compoundName+m_name; } if (lref) { - //url=(QCString)"doxygen=\""+lref+":\" href=\""+fileName; - exampleList = 0; - exampleDict = 0; + m_exampleSDict = 0; } else { - //url="href=\""+fileName; - exampleList = new ExampleList; - exampleDict = new ExampleDict(17); + m_exampleSDict = new ExampleSDict(17); } - memListFileName=convertNameToFile(compoundName+nm+"-members"); - inherits = new BaseClassList; - inherits->setAutoDelete(TRUE); - inheritedBy = new BaseClassList; - inheritedBy->setAutoDelete(TRUE); - allMemberNameInfoList = new MemberNameInfoList; - allMemberNameInfoList->setAutoDelete(TRUE); - allMemberNameInfoDict = new MemberNameInfoDict(257); + m_memListFileName=convertNameToFile(compoundName+m_name+"-members"); + m_inherits = new BaseClassList; + m_inherits->setAutoDelete(TRUE); + m_inheritedBy = new BaseClassList; + m_inheritedBy->setAutoDelete(TRUE); + m_allMemberNameInfoSDict = new MemberNameInfoSDict(257); + m_allMemberNameInfoSDict->setAutoDelete(TRUE); visited=FALSE; setReference(lref); - incInfo=0; - tempArgs=0; - prot=Public; - nspace=0; - fileDef=0; - usesImplClassDict=0; - usesIntfClassDict=0; - memberGroupList = new MemberGroupList; - memberGroupList->setAutoDelete(TRUE); - memberGroupDict = new MemberGroupDict(17); + m_incInfo=0; + m_tempArgs=0; + m_prot=Public; + m_nspace=0; + m_fileDef=0; + m_usesImplClassDict=0; + m_usesIntfClassDict=0; + m_memberGroupList = new MemberGroupList; + m_memberGroupList->setAutoDelete(TRUE); + m_memberGroupDict = new MemberGroupDict(17); + m_innerClasses = new ClassSDict(17); int i=name().findRev("::"); if (i==-1) { - scopelessName=name(); + m_scopelessName=name(); } else { - scopelessName=name().right(name().length()-i-2); + m_scopelessName=name().right(name().length()-i-2); } - subGrouping=TRUE; + m_subGrouping=TRUE; + m_isTemplBaseClass=-1; + m_templateMapping = new StringDict; + m_templateMapping->setAutoDelete(TRUE); } // destroy the class definition ClassDef::~ClassDef() { - delete inherits; - delete inheritedBy; - delete allMemberNameInfoList; - delete allMemberNameInfoDict; - delete exampleList; - delete exampleDict; - delete usesImplClassDict; - delete usesIntfClassDict; - delete incInfo; - delete memberGroupList; - delete memberGroupDict; + delete m_inherits; + delete m_inheritedBy; + delete m_allMemberNameInfoSDict; + delete m_exampleSDict; + delete m_usesImplClassDict; + delete m_usesIntfClassDict; + delete m_incInfo; + delete m_memberGroupList; + delete m_memberGroupDict; + delete m_innerClasses; + delete m_templateMapping; } QCString ClassDef::displayName() const @@ -139,7 +136,7 @@ void ClassDef::insertBaseClass(ClassDef *cd,const char *n,Protection p, { //printf("*** insert base class %s into %s\n",cd->name().data(),name().data()); //inherits->inSort(new BaseClassDef(cd,p,s,t)); - inherits->append(new BaseClassDef(cd,n,p,s,t)); + m_inherits->append(new BaseClassDef(cd,n,p,s,t)); } // inserts a sub class in the inherited list @@ -147,34 +144,34 @@ void ClassDef::insertSubClass(ClassDef *cd,Protection p, Specifier s,const char *t) { //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data()); - inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t)); + m_inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t)); } void ClassDef::addMembersToMemberGroup() { - ::addMembersToMemberGroup(&pubTypes,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&pubMembers,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&pubAttribs,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&pubSlots,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&signals,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&dcopMethods,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&pubStaticMembers,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&pubStaticAttribs,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&proTypes,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&proMembers,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&proAttribs,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&proSlots,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&proStaticMembers,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&proStaticAttribs,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&priTypes,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&priMembers,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&priAttribs,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&priSlots,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&priStaticMembers,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&priStaticAttribs,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&friends,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&related,memberGroupDict,memberGroupList); - ::addMembersToMemberGroup(&properties,memberGroupDict,memberGroupList); + ::addMembersToMemberGroup(&pubTypes,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&pubMembers,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&pubAttribs,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&pubSlots,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&signals,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&dcopMethods,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&pubStaticMembers,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&pubStaticAttribs,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&proTypes,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&proMembers,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&proAttribs,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&proSlots,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&proStaticMembers,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&proStaticAttribs,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&priTypes,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&priMembers,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&priAttribs,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&priSlots,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&priStaticMembers,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&priStaticAttribs,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&friends,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&related,m_memberGroupDict,m_memberGroupList); + ::addMembersToMemberGroup(&properties,m_memberGroupDict,m_memberGroupList); } // adds new member definition to the class @@ -410,7 +407,7 @@ void ClassDef::insertMember(MemberDef *md) enumValMembers.append(md); break; case MemberDef::Function: - if (md->name()==scopelessName || // constructor + if (md->name()==m_scopelessName || // constructor (md->name().find('~')!=-1 && // hack to detect destructor md->name().find("operator")==-1 ) @@ -452,7 +449,7 @@ void ClassDef::insertMember(MemberDef *md) MemberInfo *mi = new MemberInfo((MemberDef *)md, md->protection(),md->virtualness(),FALSE); MemberNameInfo *mni=0; - if ((mni=(*allMemberNameInfoDict)[md->name()])) + if ((mni=m_allMemberNameInfoSDict->find(md->name()))) { mni->append(mi); } @@ -460,15 +457,14 @@ void ClassDef::insertMember(MemberDef *md) { mni = new MemberNameInfo(md->name()); mni->append(mi); - allMemberNameInfoList->inSort(mni); - allMemberNameInfoDict->insert(mni->memberName(),mni); + m_allMemberNameInfoSDict->inSort(mni->memberName(),mni); } } //void ClassDef::computeMemberGroups() //{ -// MemberNameInfoListIterator mnili(*allMemberNameInfoList); +// MemberNameInfoListIterator mnili(*m_allMemberNameInfoList); // MemberNameInfo *mni; // for (;(mni=mnili.current());++mnili) // { @@ -478,10 +474,10 @@ void ClassDef::insertMember(MemberDef *md) // { // MemberDef *md=mi->memberDef; // MemberGroup *mg = md->getMemberGroup(); -// if (mg && memberGroupDict->find(mg->groupId())==0) +// if (mg && m_memberGroupDict->find(mg->groupId())==0) // { -// memberGroupDict->insert(mg->groupId(),mg); -// memberGroupList->append(mg); +// m_memberGroupDict->insert(mg->groupId(),mg); +// m_memberGroupList->append(mg); // } // } // } @@ -517,7 +513,7 @@ void ClassDef::computeAnchors() void ClassDef::distributeMemberGroupDocumentation() { - MemberGroupListIterator mgli(*memberGroupList); + MemberGroupListIterator mgli(*m_memberGroupList); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -529,7 +525,7 @@ void ClassDef::distributeMemberGroupDocumentation() // add a file name to the used files set void ClassDef::insertUsedFile(const char *f) { - if (files.find(f)==-1) files.append(f); + if (m_files.find(f)==-1) m_files.append(f); } static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) @@ -557,15 +553,15 @@ static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) void ClassDef::setIncludeFile(FileDef *fd,const char *includeName,bool local) { //printf("ClassDef::setInclude(%p,%s,%d)\n",fd,includeName,local); - if (!incInfo) incInfo=new IncludeInfo; - if ((includeName && incInfo->includeName.isEmpty()) || - (fd!=0 && incInfo->fileDef==0) + if (!m_incInfo) m_incInfo=new IncludeInfo; + if ((includeName && m_incInfo->includeName.isEmpty()) || + (fd!=0 && m_incInfo->fileDef==0) ) { //printf("Setting file info\n"); - incInfo->fileDef = fd; - incInfo->includeName = includeName; - incInfo->local = local; + m_incInfo->fileDef = fd; + m_incInfo->includeName = includeName; + m_incInfo->local = local; } } @@ -574,7 +570,7 @@ ArgumentList *ClassDef::outerTemplateArguments() const int ti; ClassDef *pcd=0; int pi=0; - if (tempArgs) return tempArgs; + if (m_tempArgs) return m_tempArgs; // find the outer most class scope while ((ti=name().find("::",pi))!=-1 && (pcd=getClass(name().left(ti)))==0 @@ -632,7 +628,7 @@ void ClassDef::writeDocumentation(OutputList &ol) if (outerTempArgList) pageTitle.prepend(" Template"); startFile(ol,getOutputFileBase(),pageTitle); startTitle(ol,getOutputFileBase()); - parseText(ol,theTranslator->trCompoundReference(name(),compType,outerTempArgList!=0)); + parseText(ol,theTranslator->trCompoundReference(name(),m_compType,outerTempArgList!=0)); endTitle(ol,getOutputFileBase(),name()); ol.startTextBlock(); @@ -643,7 +639,7 @@ void ClassDef::writeDocumentation(OutputList &ol) OutputList briefOutput(&ol); if (!briefDescription().isEmpty()) { - parseDoc(briefOutput,defFileName,defLine,name(),0,briefDescription()); + parseDoc(briefOutput,m_defFileName,m_defLine,name(),0,briefDescription()); ol+=briefOutput; ol.writeString(" \n"); ol.pushGeneratorState(); @@ -658,18 +654,18 @@ void ClassDef::writeDocumentation(OutputList &ol) } ol.writeSynopsis(); - if (incInfo) + if (m_incInfo) { - QCString nm=incInfo->includeName.isEmpty() ? - (incInfo->fileDef ? - incInfo->fileDef->docName().data() : "" + QCString nm=m_incInfo->includeName.isEmpty() ? + (m_incInfo->fileDef ? + m_incInfo->fileDef->docName().data() : "" ) : - incInfo->includeName.data(); + m_incInfo->includeName.data(); if (!nm.isEmpty()) { ol.startTypewriter(); ol.docify("#include "); - if (incInfo->local) + if (m_incInfo->local) ol.docify("\""); else ol.docify("<"); @@ -678,16 +674,16 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.docify(nm); ol.disableAllBut(OutputGenerator::Html); ol.enable(OutputGenerator::Html); - if (incInfo->fileDef) + if (m_incInfo->fileDef) { - ol.writeObjectLink(0,incInfo->fileDef->includeName(),0,nm); + ol.writeObjectLink(0,m_incInfo->fileDef->includeName(),0,nm); } else { ol.docify(nm); } ol.popGeneratorState(); - if (incInfo->local) + if (m_incInfo->local) ol.docify("\""); else ol.docify(">"); @@ -711,11 +707,11 @@ void ClassDef::writeDocumentation(OutputList &ol) // write subclasses int count; - if ((count=inherits->count())>0) + if ((count=m_inherits->count())>0) { //parseText(ol,theTranslator->trInherits()+" "); - QCString inheritLine = theTranslator->trInheritsList(inherits->count()); + QCString inheritLine = theTranslator->trInheritsList(m_inherits->count()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -724,7 +720,7 @@ void ClassDef::writeDocumentation(OutputList &ol) parseText(ol,inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=inherits->at(entryIndex); + BaseClassDef *bcd=m_inherits->at(entryIndex); if (ok && bcd) { ClassDef *cd=bcd->classDef; @@ -765,9 +761,9 @@ void ClassDef::writeDocumentation(OutputList &ol) } // write subclasses - if ((count=inheritedBy->count())>0) + if ((count=m_inheritedBy->count())>0) { - QCString inheritLine = theTranslator->trInheritedByList(inheritedBy->count()); + QCString inheritLine = theTranslator->trInheritedByList(m_inheritedBy->count()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -776,7 +772,7 @@ void ClassDef::writeDocumentation(OutputList &ol) parseText(ol,inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=inheritedBy->at(entryIndex); + BaseClassDef *bcd=m_inheritedBy->at(entryIndex); if (ok && bcd) { ClassDef *cd=bcd->classDef; @@ -801,19 +797,19 @@ void ClassDef::writeDocumentation(OutputList &ol) count=0; BaseClassDef *ibcd; - ibcd=inheritedBy->first(); + ibcd=m_inheritedBy->first(); while (ibcd) { ClassDef *icd=ibcd->classDef; if ( icd->isVisibleInHierarchy()) count++; - ibcd=inheritedBy->next(); + ibcd=m_inheritedBy->next(); } - ibcd=inherits->first(); + ibcd=m_inherits->first(); while (ibcd) { ClassDef *icd=ibcd->classDef; if ( icd->isVisibleInHierarchy()) count++; - ibcd=inherits->next(); + ibcd=m_inherits->next(); } @@ -879,10 +875,11 @@ void ClassDef::writeDocumentation(OutputList &ol) } // write link to list of all members (HTML only) - if (allMemberNameInfoList->count()>0 && !Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) + if (m_allMemberNameInfoSDict->count()>0 && + !Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) { ol.disableAllBut(OutputGenerator::Html); - ol.startTextLink(memListFileName,0); + ol.startTextLink(m_memListFileName,0); parseText(ol,theTranslator->trListOfAllMembers()); ol.endTextLink(); ol.enableAll(); @@ -894,11 +891,11 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.startMemberSections(); // write user defined member groups - MemberGroupListIterator mgli(*memberGroupList); + MemberGroupListIterator mgli(*m_memberGroupList); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - if (!mg->allMembersInSameSection() || !subGrouping) // group is in its own section + if (!mg->allMembersInSameSection() || !m_subGrouping) // group is in its own section { mg->writeDeclarations(ol,this,0,0,0); } @@ -908,40 +905,52 @@ void ClassDef::writeDocumentation(OutputList &ol) } } - // non static public members + // public types pubTypes.writeDeclarations(ol,this,0,0,0,theTranslator->trPublicTypes(),0); - pubMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trPublicMembers(),0); - pubAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trPublicAttribs(),0); + + // public methods pubSlots.writeDeclarations(ol,this,0,0,0,theTranslator->trPublicSlots(),0); signals.writeDeclarations(ol,this,0,0,0,theTranslator->trSignals(),0); dcopMethods.writeDeclarations(ol,this,0,0,0,theTranslator->trDCOPMethods(),0); properties.writeDeclarations(ol,this,0,0,0,theTranslator->trProperties(),0); - - // static public members + pubMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trPublicMembers(),0); pubStaticMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trStaticPublicMembers(),0); + + // public attribs + pubAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trPublicAttribs(),0); pubStaticAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trStaticPublicAttribs(),0); - // protected non-static members + // protected types proTypes.writeDeclarations(ol,this,0,0,0,theTranslator->trProtectedTypes(),0); - proMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trProtectedMembers(),0); - proAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trProtectedAttribs(),0); + + // protected methods proSlots.writeDeclarations(ol,this,0,0,0,theTranslator->trProtectedSlots(),0); - // protected static members + proMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trProtectedMembers(),0); proStaticMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trStaticProtectedMembers(),0); + + // protected attribs + proAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trProtectedAttribs(),0); proStaticAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trStaticProtectedAttribs(),0); if (Config_getBool("EXTRACT_PRIVATE")) { - // private non-static members + // private types priTypes.writeDeclarations(ol,this,0,0,0,theTranslator->trPrivateTypes(),0); - priMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trPrivateMembers(),0); - priAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trPrivateAttribs(),0); + + // private members priSlots.writeDeclarations(ol,this,0,0,0,theTranslator->trPrivateSlots(),0); - // private static members + priMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trPrivateMembers(),0); priStaticMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trStaticPrivateMembers(),0); + + // private attribs + priAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trPrivateAttribs(),0); priStaticAttribs.writeDeclarations(ol,this,0,0,0,theTranslator->trStaticPrivateAttribs(),0); } + + // friends friends.writeDeclarations(ol,this,0,0,0,theTranslator->trFriends(),0); + + // related functions related.writeDeclarations(ol,this,0,0,0, theTranslator->trRelatedFunctions(), theTranslator->trRelatedSubscript() @@ -985,7 +994,7 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.disableAllBut(OutputGenerator::RTF); ol.newParagraph(); ol.popGeneratorState(); - parseDoc(ol,defFileName,defLine,name(),0,documentation()+"\n"); + parseDoc(ol,m_defFileName,m_defLine,name(),0,documentation()+"\n"); } // write examples if (exampleFlag) @@ -997,7 +1006,7 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.endDescTitle(); ol.writeDescItem(); ol.newParagraph(); - writeExample(ol,exampleList); + writeExample(ol,m_exampleSDict); //ol.endDescItem(); ol.endDescList(); } @@ -1040,10 +1049,10 @@ void ClassDef::writeDocumentation(OutputList &ol) { ol.disable(OutputGenerator::Man); ol.writeRuler(); - parseText(ol,theTranslator->trGeneratedFromFiles(compType,files.count()==1)); + parseText(ol,theTranslator->trGeneratedFromFiles(m_compType,m_files.count()==1)); bool first=TRUE; - const char *file = files.first(); + const char *file = m_files.first(); while (file) { bool ambig; @@ -1077,7 +1086,7 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.docify(fd->name()); } } - file=files.next(); + file=m_files.next(); } if (!first) ol.endItemList(); } @@ -1106,12 +1115,13 @@ void ClassDef::writeDocumentation(OutputList &ol) // write the list of all (inherited) members for this class void ClassDef::writeMemberList(OutputList &ol) { - if (allMemberNameInfoList->count()==0 || Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) return; + if (m_allMemberNameInfoSDict->count()==0 || + Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) return; // only for HTML ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - startFile(ol,memListFileName,theTranslator->trMemberList()); + startFile(ol,m_memListFileName,theTranslator->trMemberList()); startTitle(ol,0); parseText(ol,name()+" "+theTranslator->trMemberList()); endTitle(ol,0,0); @@ -1121,8 +1131,10 @@ void ClassDef::writeMemberList(OutputList &ol) ol.startItemList(); - MemberNameInfo *mni=allMemberNameInfoList->first(); - while (mni) + //MemberNameInfo *mni=m_allMemberNameInfoList->first(); + MemberNameInfoSDict::Iterator mnii(*m_allMemberNameInfoSDict); + MemberNameInfo *mni; + for (mnii.toFirst();(mni=mnii.current());++mnii) { MemberInfo *mi=mni->first(); while (mi) @@ -1253,7 +1265,6 @@ void ClassDef::writeMemberList(OutputList &ol) } mi=mni->next(); } - mni=allMemberNameInfoList->next(); } ol.endItemList(); endFile(ol); @@ -1265,14 +1276,13 @@ void ClassDef::writeMemberList(OutputList &ol) bool ClassDef::addExample(const char *anchor,const char *nameStr, const char *file) { - if (exampleDict && !exampleDict->find(nameStr)) + if (m_exampleSDict && !m_exampleSDict->find(nameStr)) { Example *e=new Example; e->anchor=anchor; e->name=nameStr; e->file=file; - exampleDict->insert(nameStr,e); - exampleList->inSort(e); + m_exampleSDict->inSort(nameStr,e); return TRUE; } return FALSE; @@ -1281,24 +1291,24 @@ bool ClassDef::addExample(const char *anchor,const char *nameStr, // returns TRUE if this class is used in an example bool ClassDef::hasExamples() { - if (exampleList==0) + if (m_exampleSDict==0) return FALSE; else - return exampleList->count()>0; + return m_exampleSDict->count()>0; } void ClassDef::setTemplateArguments(ArgumentList *al) { if (al==0) return; - if (!tempArgs) delete tempArgs; // delete old list if needed - tempArgs=new ArgumentList; - tempArgs->setAutoDelete(TRUE); + if (!m_tempArgs) delete m_tempArgs; // delete old list if needed + m_tempArgs=new ArgumentList; + m_tempArgs->setAutoDelete(TRUE); ArgumentListIterator ali(*al); Argument *a; for (;(a=ali.current());++ali) { - tempArgs->append(new Argument(*a)); + m_tempArgs->append(new Argument(*a)); } } @@ -1306,7 +1316,7 @@ void ClassDef::setTemplateArguments(ArgumentList *al) bool ClassDef::hasNonReferenceSuperClass() { bool found=!isReference(); - BaseClassListIterator bcli(*inheritedBy); + BaseClassListIterator bcli(*m_inheritedBy); for ( ; bcli.current() && !found ; ++bcli ) found=found || bcli.current()->classDef->hasNonReferenceSuperClass(); return found; @@ -1329,13 +1339,22 @@ void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup) if (!cn.isEmpty() && cn.at(0)!='@' && md) { ol.docify(" "); - ol.writeObjectLink(0,0,md->anchor(),cn); + if (isLinkable()) + { + ol.writeObjectLink(0,0,md->anchor(),cn); + } + else + { + ol.startBold(); + ol.docify(cn); + ol.endBold(); + } } ol.docify(" {"); ol.endMemberItem(FALSE); // write user defined member groups - MemberGroupListIterator mgli(*memberGroupList); + MemberGroupListIterator mgli(*m_memberGroupList); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { @@ -1397,19 +1416,24 @@ void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup) /*! a link to this class is possible within this project */ bool ClassDef::isLinkableInProject() { - return !name().isEmpty() && name().find('@')==-1 && - (prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && - hasDocumentation() && !isReference(); + return !name().isEmpty() && /* no name */ + m_isTemplBaseClass==-1 && /* template base class */ + name().find('@')==-1 && /* anonymous compound */ + (m_prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && /* private */ + hasDocumentation() && /* documented */ + !isReference(); /* not an external reference */ } /*! the class is visible in a class diagram, or class hierarchy */ bool ClassDef::isVisibleInHierarchy() { return // show all classes or a subclass is visible - (Config_getBool("ALLEXTERNALS") || hasNonReferenceSuperClass()) && + (Config_getBool("ALLEXTERNALS") || hasNonReferenceSuperClass()) && // and not an annonymous compound name().find('@')==-1 && + // and not an inherited template argument + m_isTemplBaseClass==-1 && // and not privately inherited - (prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && + (m_prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && // documented or show anyway or documentation is external (hasDocumentation() || !Config_getBool("HIDE_UNDOC_CLASSES") || isReference()); } @@ -1459,11 +1483,11 @@ void ClassDef::mergeMembers() // merge the members in the base class of this inheritance branch first bClass->mergeMembers(); - MemberNameInfoList *srcMnl = bClass->memberNameInfoList(); - MemberNameInfoDict *dstMnd = memberNameInfoDict(); - MemberNameInfoList *dstMnl = memberNameInfoList(); + MemberNameInfoSDict *srcMnd = bClass->memberNameInfoSDict(); + MemberNameInfoSDict *dstMnd = memberNameInfoSDict(); + //MemberNameInfoList *dstMnl = memberNameInfoList(); - MemberNameInfoListIterator srcMnili(*srcMnl); + MemberNameInfoSDict::Iterator srcMnili(*srcMnd); MemberNameInfo *srcMni; for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) { @@ -1624,15 +1648,16 @@ void ClassDef::mergeMembers() } } - // add it to the list and dictionary - dstMnl->append(newMni); - dstMnd->insert(newMni->memberName(),newMni); + // add it to the dictionary + //dstMnl->append(newMni); + dstMnd->append(newMni->memberName(),newMni); } } } } //---------------------------------------------------------------------------- + /*! Builds up a dictionary of all classes that are used by the state of this * class (the "implementation"). * Must be called before mergeMembers() is called! @@ -1640,7 +1665,7 @@ void ClassDef::mergeMembers() void ClassDef::determineImplUsageRelation() { - MemberNameInfoListIterator mnili(*allMemberNameInfoList); + MemberNameInfoSDict::Iterator mnili(*m_allMemberNameInfoSDict); MemberNameInfo *mni; for (;(mni=mnili.current());++mnili) { @@ -1652,42 +1677,47 @@ void ClassDef::determineImplUsageRelation() if (md->isVariable()) // for each member variable in this class { QCString type=removeRedundantWhiteSpace(md->typeString()); - int typeLen=type.length(); - static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*"); //printf("in class %s found var type=`%s' name=`%s'\n", // name().data(),type.data(),md->name().data()); - int p=0,i,l; + int pos=0; + QCString usedClassName; + QCString templSpec; bool found=FALSE; - if (typeLen>0) + while (extractClassNameFromType(type,pos,usedClassName,templSpec) && !found) { - while ((i=re.match(type,p,&l))!=-1 && !found) // for each class name in the type + //printf("usedClassName=`%s' templSpec=%s\n",usedClassName.data(),templSpec.data()); + // check if usedClassName is a template argument of its class + ClassDef *cd=md->getClassDef(); + if (cd && cd->templateArguments()) { - int ts=i+l; - int te=ts; - while (type.at(ts)==' ' && tstemplateArguments()); + Argument *arg; + int count=0; + for (ali.toFirst();(arg=ali.current());++ali,++count) { - // locate end of template - te=ts+1; - int brCount=1; - while (tename==usedClassName) // type is a template argument { - if (type.at(te)=='<') - { - if (te') - { - if (te') te++; else brCount--; - } - te++; + found=TRUE; + if (m_usesImplClassDict==0) m_usesImplClassDict = new UsesClassDict(257); + cd = new ClassDef(cd->getDefFileName(),cd->getDefLine(), + usedClassName,ClassDef::Class); + cd->setIsTemplateBaseClass(count); + UsesClassDef *ucd = new UsesClassDef(cd); + m_usesImplClassDict->insert(cd->name(),ucd); + ucd->templSpecifiers = templSpec; + ucd->addAccessor(md->name()); + Doxygen::hiddenClasses.append(cd); + //printf("Adding used template argument %s to class %s\n", + // cd->name().data(),name().data()); + //printf("Adding accessor %s to class %s\n", + // md->name().data(),ucd->classDef->name().data()); } } - QCString templSpec; - if (te>ts) templSpec = type.mid(ts,te-ts); - // TODO: also check using Nx::Cx cases here! - QCString usedClassName = type.mid(i,l); - ClassDef *cd=0; + } + + if (!found) + { + cd=0; if (getNamespaceDef()!=0) { cd=getResolvedClass(getNamespaceDef()->name()+"::"+usedClassName,0,&templSpec); @@ -1698,12 +1728,12 @@ void ClassDef::determineImplUsageRelation() if (cd) // class exists { found=TRUE; - if (usesImplClassDict==0) usesImplClassDict = new UsesClassDict(257); - UsesClassDef *ucd=usesImplClassDict->find(cd->name()); + if (m_usesImplClassDict==0) m_usesImplClassDict = new UsesClassDict(257); + UsesClassDef *ucd=m_usesImplClassDict->find(cd->name()); if (ucd==0 || ucd->templSpecifiers!=templSpec) { ucd = new UsesClassDef(cd); - usesImplClassDict->insert(cd->name(),ucd); + m_usesImplClassDict->insert(cd->name(),ucd); ucd->templSpecifiers = templSpec; //printf("Adding used class %s to class %s\n", // cd->name().data(),name().data()); @@ -1712,17 +1742,16 @@ void ClassDef::determineImplUsageRelation() //printf("Adding accessor %s to class %s\n", // md->name().data(),ucd->classDef->name().data()); } - p=i+l; } } } } } #ifdef DUMP - if (usesClassDict) + if (m_usesClassDict) { msg("Class %s uses the following classes:\n",name().data()); - UsesClassDictIterator ucdi(*usesClassDict); + UsesClassDictIterator ucdi(*m_usesClassDict); UsesClassDef *ucd; for (;(ucd=ucdi.current());++ucdi) { @@ -1756,15 +1785,15 @@ void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr) if (cd==0) cd=getClass(type.mid(i,l)); // TODO: also try inbetween scopes! if (cd && cd!=this && !isBaseClass(cd)) { - if (usesIntfClassDict==0) + if (m_usesIntfClassDict==0) { - usesIntfClassDict = new UsesClassDict(257); + m_usesIntfClassDict = new UsesClassDict(257); } - UsesClassDef *ucd=usesIntfClassDict->find(cd->name()); + UsesClassDef *ucd=m_usesIntfClassDict->find(cd->name()); if (ucd==0) { ucd = new UsesClassDef(cd); - usesIntfClassDict->insert(cd->name(),ucd); + m_usesIntfClassDict->insert(cd->name(),ucd); //printf("in class `%s' adding used intf class `%s'\n", // name().data(),cd->name().data()); } @@ -1778,7 +1807,7 @@ void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr) void ClassDef::determineIntfUsageRelation() { - MemberNameInfoListIterator mnili(*allMemberNameInfoList); + MemberNameInfoSDict::Iterator mnili(*m_allMemberNameInfoList); MemberNameInfo *mni; for (;(mni=mnili.current());++mnili) { @@ -1824,12 +1853,12 @@ void ClassDef::determineIntfUsageRelation() PackageDef *ClassDef::packageDef() const { - return fileDef ? fileDef->packageDef() : 0; + return m_fileDef ? m_fileDef->packageDef() : 0; } QCString ClassDef::compoundTypeString() const { - switch (compType) + switch (m_compType) { case Class: return "class"; case Struct: return "struct"; @@ -1844,21 +1873,94 @@ QCString ClassDef::getOutputFileBase() const { if (isReference()) { - return fileName; + return m_fileName; } else { - return convertNameToFile(fileName); + return convertNameToFile(m_fileName); } } QCString ClassDef::getFileBase() const { - return fileName; + return m_fileName; } QCString ClassDef::getSourceFileBase() const { - return convertNameToFile(fileName+"-source"); + return convertNameToFile(m_fileName+"-source"); +} + +void ClassDef::setGroupDefForAllMembers(GroupDef *gd) +{ + gd->addClass(this); + //printf("ClassDef::setGroupDefForAllMembers(%s)\n",gd->name().data()); + MemberNameInfoSDict::Iterator mnili(*m_allMemberNameInfoSDict); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) + { + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + MemberDef *md=mi->memberDef; + md->setGroupDef(gd); + gd->insertMember(md,TRUE); + ClassDef *innerClass = md->getClassDefOfAnonymousType(); + if (innerClass) innerClass->setGroupDefForAllMembers(gd); + } + } +} + +void ClassDef::addInnerCompound(Definition *d) +{ + m_innerClasses->inSort(d->localName(),(ClassDef *)d); +} + +Definition *ClassDef::findInnerCompound(const char *name) +{ + if (name==0) return 0; + return m_innerClasses->find(name); +} + +void ClassDef::initTemplateMapping() +{ + m_templateMapping->clear(); + ArgumentList *al = templateArguments(); + if (al) + { + ArgumentListIterator ali(*al); + Argument *arg; + for (ali.toFirst();(arg=ali.current());++ali) + { + setTemplateArgumentMapping(arg->name,arg->defval); + } + } +} + +void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual) +{ + //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual); + if (m_templateMapping && formal) + { + if (m_templateMapping->find(formal)) + { + m_templateMapping->remove(formal); + } + m_templateMapping->insert(formal,new QCString(actual)); + } +} + +QCString ClassDef::getTemplateArgumentMapping(const char *formal) const +{ + if (m_templateMapping && formal) + { + QCString *s = m_templateMapping->find(formal); + if (s) + { + return *s; + } + } + return ""; } diff --git a/src/classdef.h b/src/classdef.h index 63dabd9..7869759 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -29,21 +29,21 @@ class MemberDict; class ClassList; +class ClassSDict; class OutputList; class FileDef; class BaseClassList; -class MemberInfoList; -class MemberInfoDict; class NamespaceDef; class MemberDef; -class ExampleList; -class MemberNameInfoList; -class MemberNameInfoDict; +class ExampleSDict; +class MemberNameInfoSDict; class UsesClassDict; class MemberGroupList; class MemberGroupDict; class QTextStream; class PackageDef; +class GroupDef; +class StringDict; struct IncludeInfo; /*! \brief This class contains all information about a compound. @@ -76,7 +76,7 @@ class ClassDef : public Definition QCString displayName() const; /*! Returns the type of compound this is */ - CompoundType compoundType() const { return compType; } + CompoundType compoundType() const { return m_compType; } /*! Returns the type of compound as a string */ QCString compoundTypeString() const; @@ -84,21 +84,16 @@ class ClassDef : public Definition /*! Returns the list of base classes from which this class directly * inherits. */ - BaseClassList *baseClasses() { return inherits; } + BaseClassList *baseClasses() { return m_inherits; } /*! Returns the list of sub classes that directly inherit from this class */ - BaseClassList *subClasses() { return inheritedBy; } - - /*! Returns a list of all members. This includes any inherited members. - * Members are sorted alphabetically. - */ - MemberNameInfoList *memberNameInfoList() { return allMemberNameInfoList; } + BaseClassList *subClasses() { return m_inheritedBy; } /*! Returns a dictionary of all members. This includes any inherited * members. Members are sorted alphabetically. */ - MemberNameInfoDict *memberNameInfoDict() { return allMemberNameInfoDict; } + MemberNameInfoSDict *memberNameInfoSDict() { return m_allMemberNameInfoSDict; } void writeDocumentation(OutputList &ol); void writeMemberList(OutputList &ol); @@ -107,7 +102,7 @@ class ClassDef : public Definition /*! Return the protection level (Public,Protected,Private) in which * this compound was found. */ - Protection protection() const { return prot; } + Protection protection() const { return m_prot; } /*! returns TRUE iff a link is possible to an item within this project. */ @@ -127,7 +122,7 @@ class ClassDef : public Definition /*! Returns the template arguments of this class * Will return 0 if not applicable. */ - ArgumentList *templateArguments() const { return tempArgs; } + ArgumentList *templateArguments() const { return m_tempArgs; } /*! Returns the template arguments that this nested class "inherits" * from its outer class (doxygen assumes there is only one!). @@ -138,12 +133,12 @@ class ClassDef : public Definition /*! Returns the namespace this compound is in, or 0 if it has a global * scope. */ - NamespaceDef *getNamespaceDef() { return nspace; } + NamespaceDef *getNamespaceDef() { return m_nspace; } /*! Returns the file in which this compound's definition can be found. * Should not return 0 (but it might be a good idea to check anyway). */ - FileDef *getFileDef() const { return fileDef; } + FileDef *getFileDef() const { return m_fileDef; } /*! Returns the Java package this class is in or 0 if not applicable. */ @@ -155,16 +150,24 @@ class ClassDef : public Definition */ bool isBaseClass(ClassDef *bcd); + /*! Is this an artificial class that is the template argument of + * a class. If so the argument number is returned, otherwise -1 + * is returned. + */ + int isTemplateBaseClass() const { return m_isTemplBaseClass; } + UsesClassDict *usedImplementationClasses() const { - return usesImplClassDict; + return m_usesImplClassDict; } UsesClassDict *usedInterfaceClasses() const { - return usesIntfClassDict; + return m_usesIntfClassDict; } - + + virtual Definition *findInnerCompound(const char *name); + /* member lists by protection */ MemberList pubMembers; MemberList proMembers; @@ -200,7 +203,7 @@ class ClassDef : public Definition MemberList variableMembers; MemberList propertyMembers; - /*! \} */ + /*! \} Public API */ /*! \name Doxygen internal API * \{ @@ -217,16 +220,24 @@ class ClassDef : public Definition bool addExample(const char *anchor,const char *name, const char *file); void addMembersToMemberGroup(); void distributeMemberGroupDocumentation(); - void setNamespace(NamespaceDef *nd) { nspace = nd; } + void setNamespace(NamespaceDef *nd) { m_nspace = nd; } void setTemplateArguments(ArgumentList *al); void mergeMembers(); - void setFileDef(FileDef *fd) { fileDef=fd; } + void setFileDef(FileDef *fd) { m_fileDef=fd; } void determineImplUsageRelation(); void determineIntfUsageRelation(); - void setSubGrouping(bool enabled) { subGrouping = enabled; } - void setProtection(Protection p) { prot=p; } + void setSubGrouping(bool enabled) { m_subGrouping = enabled; } + void setProtection(Protection p) { m_prot=p; } + void setGroupDefForAllMembers(GroupDef *g); + void addInnerCompound(Definition *d); + void setIsTemplateBaseClass(int num) { m_isTemplBaseClass = num; } + void initTemplateMapping(); + void setTemplateArgumentMapping(const char *formal,const char *actual); + QCString getTemplateArgumentMapping(const char *formal) const; /*! Creates a new compound definition. + * \param outerScope class, file or namespace in which this class is + * defined. * \param fileName full path and file name in which this compound was * found. * \param startLine line number where the definition of this compound @@ -252,37 +263,99 @@ class ClassDef : public Definition bool hasExamples(); bool hasNonReferenceSuperClass(); - /*! \} */ + /*! \} Interal API */ private: - QCString fileName; // HTML containing the class docs - IncludeInfo *incInfo; // header file to refer to - QCString incName; // alternative include file name - QCString memListFileName; - QCString scopelessName; // name without any scopes - BaseClassList *inherits; - BaseClassList *inheritedBy; - NamespaceDef *nspace; // the namespace this class is in + /*! file name that forms the base for the output file containing the + * class documentation. For compatibility with Qt (e.g. links via tag + * files) this name cannot be derived from the class name directly. + */ + QCString m_fileName; + + /*! Include information about the header file should be included + * in the documentation. 0 by default, set by setIncludeFile(). + */ + IncludeInfo *m_incInfo; + + /*! file name that forms the base for the "list of members" for this + * class. + */ + QCString m_memListFileName; + + /*! Bare name of the class without any scoping prefixes + * (like for nested classes and classes inside namespaces) + */ + QCString m_scopelessName; + + /*! List of base class (or super-classes) from which this class derives + * directly. + */ + BaseClassList *m_inherits; + + /*! List of sub-classes that directly derive from this class + */ + BaseClassList *m_inheritedBy; + + /*! Namespace this class is part of + * (this is the inner most namespace in case of nested namespaces) + */ + NamespaceDef *m_nspace; + + /*! File this class is defined in */ + FileDef *m_fileDef; + + /*! List of all members (including inherited members) */ + MemberNameInfoSDict *m_allMemberNameInfoSDict; + + /*! Template arguments of this class */ + ArgumentList *m_tempArgs; + + /*! Files that were used for generating the class documentation. */ + QStrList m_files; + + /*! Examples that use this class */ + ExampleSDict *m_exampleSDict; + + /*! Holds the kind of "class" this is. */ + CompoundType m_compType; + + /*! The protection level in which this class was found. + * Typically Public, but for nested classes this can also be Protected + * or Private. + */ + Protection m_prot; + + /*! Does this class group its user-grouped members + * as a sub-section of the normal (public/protected/..) + * groups? + */ + bool m_subGrouping; + + /*! The inner classes contained in this class. Will be 0 if there are + * no inner classes. + */ + ClassSDict *m_innerClasses; /* user defined member groups */ - MemberGroupList *memberGroupList; - MemberGroupDict *memberGroupDict; - - MemberNameInfoList *allMemberNameInfoList; - MemberNameInfoDict *allMemberNameInfoDict; - ArgumentList *tempArgs; - QStrList files; - ExampleList *exampleList; - ExampleDict *exampleDict; - CompoundType compType; - Protection prot; - FileDef *fileDef; - UsesClassDict *usesImplClassDict; - UsesClassDict *usesIntfClassDict; - - bool subGrouping; // does this class group its user-grouped members - // as a sub-section of the normal (public/protected/..) - // groups? + MemberGroupList *m_memberGroupList; + MemberGroupDict *m_memberGroupDict; + + /* classes for the collaboration diagram */ + UsesClassDict *m_usesImplClassDict; + UsesClassDict *m_usesIntfClassDict; + + /*! Is this a class that exists because of template class that + * inherited one of it's template arguments. If so that this + * variable indicate the template argument number, otherwise + * this is -1 + */ + int m_isTemplBaseClass; + + /*! A mapping used by template classes, which maps formal + * template arguments to their actual instantiations. + * This is used while generating inheritance graphs. + */ + StringDict *m_templateMapping; }; /*! \brief Class that contains information about a usage relation. diff --git a/src/classlist.cpp b/src/classlist.cpp index bd3874e..ca05275 100644 --- a/src/classlist.cpp +++ b/src/classlist.cpp @@ -35,9 +35,15 @@ int ClassList::compareItems(GCI item1, GCI item2) { ClassDef *c1=(ClassDef *)item1; ClassDef *c2=(ClassDef *)item2; - //int prefixLength = Config::instance()->get("").length(); - //int i1 = c1->name().left(prefixLength)==Config::instance()->get("") ? prefixLength : 0; - //int i2 = c2->name().left(prefixLength)==Config::instance()->get("") ? prefixLength : 0; + return stricmp(c1->name().data()+getPrefixIndex(c1->name()), + c2->name().data()+getPrefixIndex(c2->name()) + ); +} + +int ClassSDict::compareItems(GCI item1, GCI item2) +{ + ClassDef *c1=(ClassDef *)item1; + ClassDef *c2=(ClassDef *)item2; return stricmp(c1->name().data()+getPrefixIndex(c1->name()), c2->name().data()+getPrefixIndex(c2->name()) ); @@ -48,13 +54,14 @@ ClassListIterator::ClassListIterator(const ClassList &cllist) : { } -void ClassList::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter,const char *header) +void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter,const char *header) { if (count()>0) { - ClassDef *cd=first(); + ClassSDict::Iterator sdi(*this); + ClassDef *cd=0; bool found=FALSE; - while (cd) + for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->name().find('@')==-1 && (filter==0 || *filter==cd->compoundType()) @@ -124,7 +131,6 @@ void ClassList::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *fi } } } - cd=next(); } if (found) ol.endMemberList(); } diff --git a/src/classlist.h b/src/classlist.h index 02521d0..23c247e 100644 --- a/src/classlist.h +++ b/src/classlist.h @@ -22,6 +22,7 @@ #include #include "classdef.h" +#include "sortdict.h" class ClassList : public QList { @@ -30,8 +31,6 @@ class ClassList : public QList ~ClassList(); int compareItems(GCI item1,GCI item2); - void writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter=0, - const char *header=0); }; class ClassListIterator : public QListIterator @@ -47,4 +46,14 @@ class ClassDict : public QDict ~ClassDict() {} }; +class ClassSDict : public SDict +{ + public: + ClassSDict(int size) : SDict(size) {} + ~ClassSDict() {} + int compareItems(GCI item1,GCI item2); + void writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter=0, + const char *header=0); +}; + #endif diff --git a/src/definition.cpp b/src/definition.cpp index 1beeba9..87f5855 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -31,26 +31,33 @@ Definition::Definition(const char *df,int dl, const char *name,const char *b,const char *d) { - defFileName = df; - defLine = dl; - n=name; - brief=b; - doc=d; - sectionDict=0, - startBodyLine=endBodyLine=-1, - bodyDef=0; - sourceRefList=0; - sourceRefDict=0; + m_defFileName = df; + m_defLine = dl; + m_name=name; + m_localName=name; + int i=m_localName.findRev("::"); + if (i!=-1) + { + m_localName=m_localName.right(m_localName.length()-i-2); + } + m_brief=b; + m_doc=d; + m_sectionDict=0, + m_startBodyLine=m_endBodyLine=-1, + m_bodyDef=0; + m_sourceRefList=0; + m_sourceRefDict=0; m_todoId=0; m_testId=0; m_bugId=0; + m_outerScope=0; } Definition::~Definition() { - delete sectionDict; - delete sourceRefList; - delete sourceRefDict; + delete m_sectionDict; + delete m_sourceRefList; + delete m_sourceRefDict; } @@ -65,13 +72,13 @@ void Definition::addSectionsToDefinition(QList *anchorList) { //printf("Add section `%s' to definition `%s'\n", // si->label.data(),n.data()); - if (sectionDict==0) + if (m_sectionDict==0) { - sectionDict = new SectionDict(17); + m_sectionDict = new SectionDict(17); } - if (sectionDict->find(*s)==0) + if (m_sectionDict->find(*s)==0) { - sectionDict->insert(*s,si); + m_sectionDict->insert(*s,si); } si->definition = this; } @@ -81,9 +88,9 @@ void Definition::addSectionsToDefinition(QList *anchorList) void Definition::writeDocAnchorsToTagFile() { - if (!Config_getString("GENERATE_TAGFILE").isEmpty() && sectionDict) + if (!Config_getString("GENERATE_TAGFILE").isEmpty() && m_sectionDict) { - QDictIterator sdi(*sectionDict); + QDictIterator sdi(*m_sectionDict); SectionInfo *si; for (;(si=sdi.current());++sdi) { @@ -99,14 +106,14 @@ void Definition::writeDocAnchorsToTagFile() void Definition::setBriefDescription(const char *b) { - brief=QCString(b).stripWhiteSpace(); - int bl=brief.length(); + m_brief=QCString(b).stripWhiteSpace(); + int bl=m_brief.length(); if (bl>0) // add puntuation if needed { - switch(brief.at(bl-1)) + switch(m_brief.at(bl-1)) { case '.': case '!': case '?': break; - default: brief+='.'; break; + default: m_brief+='.'; break; } } } @@ -219,7 +226,7 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.pushGeneratorState(); //printf("Definition::writeSourceRef %d %p\n",bodyLine,bodyDef); - if (Config_getBool("SOURCE_BROWSER") && startBodyLine!=-1 && bodyDef) + if (Config_getBool("SOURCE_BROWSER") && m_startBodyLine!=-1 && m_bodyDef) { //ol.disable(OutputGenerator::RTF); ol.newParagraph(); @@ -231,15 +238,15 @@ void Definition::writeSourceDef(OutputList &ol,const char *) if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this. { QCString lineStr,anchorStr; - lineStr.sprintf("%d",startBodyLine); - anchorStr.sprintf("l%05d",startBodyLine); + lineStr.sprintf("%d",m_startBodyLine); + anchorStr.sprintf("l%05d",m_startBodyLine); if (lineMarkerPosgetSourceFileBase(), + ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(), anchorStr,lineStr); ol.enableAll(); ol.disable(OutputGenerator::Html); @@ -253,12 +260,12 @@ void Definition::writeSourceDef(OutputList &ol,const char *) ol.disableAllBut(OutputGenerator::Html); // write file link (HTML only) - ol.writeObjectLink(0,bodyDef->getSourceFileBase(), - 0,bodyDef->name()); + ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(), + 0,m_bodyDef->name()); ol.enableAll(); ol.disable(OutputGenerator::Html); // write normal text (Latex/Man only) - ol.docify(bodyDef->name()); + ol.docify(m_bodyDef->name()); ol.enableAll(); // write text right from file marker @@ -271,12 +278,12 @@ void Definition::writeSourceDef(OutputList &ol,const char *) parseText(ol,refText.left(fileMarkerPos)); ol.disableAllBut(OutputGenerator::Html); // write file link (HTML only) - ol.writeObjectLink(0,bodyDef->getSourceFileBase(), - 0,bodyDef->name()); + ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(), + 0,m_bodyDef->name()); ol.enableAll(); ol.disable(OutputGenerator::Html); // write normal text (Latex/Man only) - ol.docify(bodyDef->name()); + ol.docify(m_bodyDef->name()); ol.enableAll(); // write text between markers @@ -285,7 +292,7 @@ void Definition::writeSourceDef(OutputList &ol,const char *) ol.disableAllBut(OutputGenerator::Html); // write line link (HTML only) - ol.writeObjectLink(0,bodyDef->getSourceFileBase(), + ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(), anchorStr,lineStr); ol.enableAll(); ol.disable(OutputGenerator::Html); @@ -316,12 +323,12 @@ void Definition::writeInlineCode(OutputList &ol,const char *scopeName) ol.pushGeneratorState(); //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(), // startBodyLine,endBodyLine,bodyDef); - if (Config_getBool("INLINE_SOURCES") && startBodyLine!=-1 && - endBodyLine>=startBodyLine && bodyDef) + if (Config_getBool("INLINE_SOURCES") && m_startBodyLine!=-1 && + m_endBodyLine>=m_startBodyLine && m_bodyDef) { QCString codeFragment; - int actualStart=startBodyLine,actualEnd=endBodyLine; - if (readCodeFragment(bodyDef->absFilePath(), + int actualStart=m_startBodyLine,actualEnd=m_endBodyLine; + if (readCodeFragment(m_bodyDef->absFilePath(), actualStart,actualEnd,codeFragment) ) { @@ -330,7 +337,7 @@ void Definition::writeInlineCode(OutputList &ol,const char *scopeName) if (definitionType()==TypeMember) setParameterList((MemberDef *)this); ol.startCodeFragment(); parseCode(ol,scopeName,codeFragment,FALSE,0, - bodyDef,actualStart,actualEnd,TRUE); + m_bodyDef,actualStart,actualEnd,TRUE); ol.endCodeFragment(); } } @@ -343,13 +350,13 @@ void Definition::writeInlineCode(OutputList &ol,const char *scopeName) void Definition::writeSourceRefs(OutputList &ol,const char *scopeName) { ol.pushGeneratorState(); - if (Config_getBool("SOURCE_BROWSER") && sourceRefList) + if (Config_getBool("SOURCE_BROWSER") && m_sourceRefList) { ol.newParagraph(); parseText(ol,theTranslator->trReferencedBy()); ol.docify(" "); - QCString ldefLine=theTranslator->trWriteList(sourceRefList->count()); + QCString ldefLine=theTranslator->trWriteList(m_sourceRefList->count()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; @@ -359,7 +366,7 @@ void Definition::writeSourceRefs(OutputList &ol,const char *scopeName) bool ok; parseText(ol,ldefLine.mid(index,newIndex-index)); uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - MemberDef *md=sourceRefList->at(entryIndex); + MemberDef *md=m_sourceRefList->at(entryIndex); if (ok && md) { QCString scope=md->getScopeString(); @@ -402,8 +409,8 @@ void Definition::writeSourceRefs(OutputList &ol,const char *scopeName) bool Definition::hasDocumentation() const { - return !doc.isEmpty() || // has detailed docs - !brief.isEmpty() || // has brief description + return !m_doc.isEmpty() || // has detailed docs + !m_brief.isEmpty() || // has brief description Config_getBool("EXTRACT_ALL"); // extract everything } @@ -419,16 +426,49 @@ void Definition::addSourceReference(MemberDef *md) name.prepend(scope+"::"); } - if (sourceRefList==0) + if (m_sourceRefList==0) { - sourceRefDict = new MemberDict(53); - sourceRefList = new MemberList; + m_sourceRefDict = new MemberDict(53); + m_sourceRefList = new MemberList; } - if (sourceRefDict->find(name)==0) + if (m_sourceRefDict->find(name)==0) { - sourceRefDict->insert(name,md); - sourceRefList->inSort(md); + m_sourceRefDict->insert(name,md); + m_sourceRefList->inSort(md); } } } +Definition *Definition::findInnerCompound(const char *) +{ + return 0; +} + +void Definition::addInnerCompound(Definition *) +{ + err("Error: Definition::addInnerCompound() called\n"); +} + +QCString Definition::qualifiedName() const +{ + //printf("start Definition::qualifiedName()\n"); + if (m_outerScope==0) return m_localName; // TODO: remove this check + + QCString qualifiedName; + if (m_outerScope->name()=="") + { + qualifiedName = m_localName.copy(); + } + else + { + qualifiedName = m_outerScope->qualifiedName()+"::"+m_localName; + } + //printf("end Definition::qualifiedName()=%s\n",qualifiedName.data()); + return qualifiedName; +}; + +QCString Definition::localName() const +{ + return m_localName; +} + diff --git a/src/definition.h b/src/definition.h index 2018525..6136cc6 100644 --- a/src/definition.h +++ b/src/definition.h @@ -47,26 +47,28 @@ class Definition /*! Destroys the definition */ virtual ~Definition(); /*! Returns the name of the definition */ - const QCString& name() const { return n; } + const QCString& name() const { return m_name; } /*! Returns the base name of the output file that contains this * definition. */ + QCString qualifiedName() const; + QCString localName() const; virtual QCString getOutputFileBase() const = 0; /*! Returns the name of the source listing of this file. */ const QCString getSourceFileBase() const { ASSERT(0); return "NULL"; } /*! Returns the detailed description of this definition */ - const QCString& documentation() const { return doc; } + const QCString& documentation() const { return m_doc; } /*! Returns the brief description of this definition */ - const QCString& briefDescription() const { return brief; } + const QCString& briefDescription() const { return m_brief; } /*! Sets a new \a name for the definition */ - void setName(const char *name) { n=name; } + void setName(const char *name) { m_name=name; } /*! Sets the documentation of this definition to \a d. */ void setDocumentation(const char *d,bool stripWhiteSpace=TRUE) { if (stripWhiteSpace) - doc=((QCString)d).stripWhiteSpace(); + m_doc=((QCString)d).stripWhiteSpace(); else - doc=d; + m_doc=d; } /*! Sets the brief description of this definition to \a b. * A dot is added to the sentence if not available. @@ -77,9 +79,9 @@ class Definition virtual bool isLinkableInProject() = 0; virtual bool isLinkable() = 0; - bool isReference() const { return !ref.isEmpty(); } - void setReference(const char *r) { ref=r; } - QCString getReference() const { return ref; } + bool isReference() const { return !m_ref.isEmpty(); } + void setReference(const char *r) { m_ref=r; } + QCString getReference() const { return m_ref; } /*! Add the list of anchors that mark the sections that are found in the * documentation. @@ -90,13 +92,13 @@ class Definition // source references void setBodySegment(int bls,int ble) { - startBodyLine=bls; - endBodyLine=ble; + m_startBodyLine=bls; + m_endBodyLine=ble; } - void setBodyDef(FileDef *fd) { bodyDef=fd; } - int getStartBodyLine() const { return startBodyLine; } - int getEndBodyLine() const { return endBodyLine; } - FileDef *getBodyDef() { return bodyDef; } + void setBodyDef(FileDef *fd) { m_bodyDef=fd; } + int getStartBodyLine() const { return m_startBodyLine; } + int getEndBodyLine() const { return m_endBodyLine; } + FileDef *getBodyDef() { return m_bodyDef; } void writeSourceDef(OutputList &ol,const char *scopeName); void writeInlineCode(OutputList &ol,const char *scopeName); void writeSourceRefs(OutputList &ol,const char *scopeName); @@ -113,28 +115,40 @@ class Definition int bugId() const { return m_bugId; } /*! returns the file in which this definition was found */ - QCString getDefFileName() const { return defFileName; } + QCString getDefFileName() const { return m_defFileName; } /*! returns the line number at which the definition was found */ - int getDefLine() const { return defLine; } + int getDefLine() const { return m_defLine; } + + virtual Definition *findInnerCompound(const char *name); + virtual Definition *getOuterScope() { return m_outerScope; } + virtual void addInnerCompound(Definition *d); + virtual void setOuterScope(Definition *d) { m_outerScope = d; } protected: - int startBodyLine; // line number of the start of the definition - int endBodyLine; // line number of the end of the definition - FileDef *bodyDef; // file definition containing the function body + int m_startBodyLine; // line number of the start of the definition + int m_endBodyLine; // line number of the end of the definition + FileDef *m_bodyDef; // file definition containing the function body // where the item was found - QCString defFileName; - int defLine; + QCString m_defFileName; + int m_defLine; + + /*! The class, namespace in which this class is located + */ + Definition *m_outerScope; + QCString m_name; // name of the definition + QCString m_localName; // local (unqualified) name of the definition + // in the future m_name should become m_localName private: - QCString n; // name of the definition - QCString brief; // brief description - QCString doc; // detailed description - QCString ref; // reference to external documentation - SectionDict *sectionDict; // dictionary of all sections - MemberList *sourceRefList; // list of entities that refer to this + //QCString m_qualifiedName; // name of the definition + QCString m_brief; // brief description + QCString m_doc; // detailed description + QCString m_ref; // reference to external documentation + SectionDict *m_sectionDict; // dictionary of all sections + MemberList *m_sourceRefList; // list of entities that refer to this // entity in their definition - MemberDict *sourceRefDict; + MemberDict *m_sourceRefDict; int m_testId; // id for test list item int m_todoId; // id for todo list item int m_bugId; // id for bug list item diff --git a/src/diagram.cpp b/src/diagram.cpp index 103bd7a..aeb78df 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -916,7 +916,7 @@ void TreeDiagram::drawConnectors(QTextStream &t,Image *image, void clearVisitFlags() { - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); ClassDef *cd; for (;(cd=cli.current());++cli) { diff --git a/src/doc.l b/src/doc.l index d04a17f..57b694c 100644 --- a/src/doc.l +++ b/src/doc.l @@ -831,6 +831,7 @@ HREF [hH][rR][eE][fF] I [iI] IMG [iI][mM][gG] INPUT [iI][nN][pP][uU][tT] +KBD [kK][bB][dD] LI [lL][iI] META [mM][eE][tT][aA] MULTICOL [mM][uU][lL][tT][iI][cC][oO][lL] @@ -2099,6 +2100,8 @@ OPMASK ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG}) "" "<"{TT}{ATTR}">" { outDoc->startTypewriter(); } "" { outDoc->endTypewriter(); } +"<"{KBD}{ATTR}">" { outDoc->startTypewriter(); } +"" { outDoc->endTypewriter(); } "<"{EM}{ATTR}">" { outDoc->startEmphasis(); } "" { outDoc->endEmphasis(); } "<"{HR}{ATTR}">" { outDoc->writeRuler(); } diff --git a/src/dot.cpp b/src/dot.cpp index d1bcc76..4aae44d 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "language.h" #include "scanner.h" +#include "defargs.h" #include #include @@ -175,6 +176,141 @@ static bool isLeaf(ClassDef *cd) return TRUE; } +/*! Builds a mapping from formal arguments of class \a tcd to the + * actual arguments stored in templSpec. To properly initialize + * the mapping with the default template values + * ClassDef::initTemplateMapping() is called once for each class graph + * (the ClassDef::visited flag is used for this). + */ +static void setTemplateInstance(QCString templSpec,ClassDef *tcd) +{ + //printf("====== setTemplateInstance(templ=%s,class=%s)\n",templSpec.data(),tcd->name().data()); + if (!templSpec.isEmpty()) + { + //if (!tcd->visited) + //{ + // tcd->visited=TRUE; + //} + ArgumentList *tempArgList = new ArgumentList; + stringToArgumentList(templSpec,tempArgList); + ArgumentListIterator ali(*tempArgList); + Argument *arg; + uint count=0; + for (ali.toFirst();(arg=ali.current());++ali,++count) + { + ArgumentList *formalArgList = tcd->templateArguments(); + Argument *formalArg=0; + //printf("arg->type=%s count=%d formalArgList=%p\n", + // arg->type.data(),count,formalArgList); + if (formalArgList && formalArgList->count()>count && + (formalArg=formalArgList->at(count))) + { + if (formalArg->name!=arg->type) + { + tcd->setTemplateArgumentMapping(formalArg->name,arg->type); + //printf("%s->setTemplateInstantation(%s,%s)\n",tcd->name().data(), + // formalArg->name.data(),arg->type.data()); + } + } + } + delete tempArgList; + } +} + +/*! Substitutes the formal template argument list \a templSpec + * of class \a cd with the actual template arguments. + * The mapping from formal to actual template is assumed to be stored + * in \a cd using setTemplateInstance(). + */ +static QCString substituteTemplateSpec(ClassDef *cd,const QCString &templSpec) +{ + QCString result; + if (!templSpec.isEmpty()) + { + ArgumentList *tempArgList = new ArgumentList; + stringToArgumentList(templSpec,tempArgList); + ArgumentListIterator ali(*tempArgList); + Argument *arg; + bool first=TRUE; + for (ali.toFirst();(arg=ali.current());) + { + if (first) result="<",first=FALSE; + QCString actual = cd->getTemplateArgumentMapping(arg->type); + if (!actual.isEmpty()) + { + result+=actual; + } + else + { + result+=arg->type; + } + ++ali; + if (ali.current()) result+=","; else result+=">"; + } + delete tempArgList; + } + //printf("substituteTemplateSpec(%s,%s)=`%s'\n",cd->name().data(),templSpec.data(),result.data()); + return removeRedundantWhiteSpace(result); +} + +/*! Determines the actual template instance of template class \a tcd that + * relates to class \a cd. The result is stored in \a tcd. + * \param cd A class + * \param tcd A template base class + * \param templSpec Actual template parameter list to be used for tcd + * \param result resulting instance class + * \param actualArg actual template instance name of the resulting class + */ +static void computeTemplateInstance( + ClassDef *cd,ClassDef *tcd,const QCString templSpec, + ClassDef *&result,QCString &actualArg + + ) +{ + //printf("====== computeTemplateInstance(%s,base=%s,templ=%s)\n", + // cd->name().data(),tcd->name().data(),templSpec.data()); + // store the specific instance inside the class + setTemplateInstance(templSpec,tcd); + int tArgNum = tcd->isTemplateBaseClass(); + if (tArgNum!=-1) + { + //printf("tArgNum=%d\n",tArgNum); + ArgumentList *formalArgList = cd->templateArguments(); + if (formalArgList) + { + //printf("formalArgList=%p\n",formalArgList); + Argument *formalArg=formalArgList->at(tArgNum); + if (formalArg) + { + //printf("formalArg=%s\n",formalArg->name.data()); + actualArg = cd->getTemplateArgumentMapping(formalArg->name); + //printf("ActualArg=%s\n",actualArg.data()); + int pos=0; + QCString name; + QCString templSpec; + while (extractClassNameFromType(actualArg,pos,name,templSpec)) + { + //printf("name=%s templSpec=%s\n",name.data(),templSpec.data()); + ClassDef *acd=getResolvedClass(name); + if (acd && !templSpec.isEmpty()) + { + // store specific template instance in the class + setTemplateInstance(templSpec,acd); + } + if (acd) + { + result = acd; + actualArg = acd->name()+templSpec; + return; + } + } + } + } + } + actualArg.resize(0); + result = 0; +} + //-------------------------------------------------------------------- class DotNodeList : public QList @@ -693,8 +829,8 @@ DotGfxHierarchyTable::DotGfxHierarchyTable() // build a graph with each class as a node and the inheritance relations // as edges - initClassHierarchy(&Doxygen::classList); - ClassListIterator cli(Doxygen::classList); + initClassHierarchy(&Doxygen::classSDict); + ClassSDict::Iterator cli(Doxygen::classSDict); ClassDef *cd; for (cli.toLast();(cd=cli.current());--cli) { @@ -784,8 +920,8 @@ int DotClassGraph::m_curNodeNumber; void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, const char *label,int distance,const char *usedName,const char *templSpec,bool base) { - //printf(":: DoxGfxUsageGraph::addClass(class=%s,parent=%s,prot=%d,label=%s,dist=%d)\n", - // cd->name().data(),n->m_label.data(),prot,label,distance); + //printf("DoxClassGraph::addClass(class=%s,parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n", + // cd->name().data(),n->m_label.data(),prot,label,distance,usedName,templSpec,base); int edgeStyle = label ? EdgeInfo::Dashed : EdgeInfo::Solid; QCString className; if (usedName) // name is a typedef @@ -850,11 +986,25 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,int distance,bool base) BaseClassDef *bcd; for ( ; (bcd=bcli.current()) ; ++bcli ) { - //printf("addClass: base=%s this=%s templ=%s\n",bcd->classDef->name().data(), - // cd->name().data(),bcd->templSpecifiers.data()); - QCString templSpec; - if (base) templSpec = bcd->templSpecifiers; - addClass(bcd->classDef,n,bcd->prot,0,distance,bcd->usedName,templSpec,base); + //printf("-------- inheritance relation %s->%s templ=`%s'\n", + // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); + QCString templSpec; + if (base) templSpec = substituteTemplateSpec( + cd,bcd->templSpecifiers); + ClassDef *acd=0; + QCString actualArg; + computeTemplateInstance(cd,bcd->classDef,templSpec,acd,actualArg); + //printf("acd=%p actualArg=%s\n",acd,actualArg.data()); + if (acd) + { + addClass(acd,n,bcd->prot,0,distance,actualArg, + templSpec,base); + } + else + { + addClass(bcd->classDef,n,bcd->prot,0,distance,bcd->usedName, + templSpec,base); + } } if (m_graphType != Inheritance) { @@ -883,8 +1033,25 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,int distance,bool base) label+=QCString("\\n")+s; } } - //printf("Found label=`%s'\n",label.data()); - addClass(ucd->classDef,n,EdgeInfo::Black,label,distance,0,ucd->templSpecifiers,base); + QCString actualArg; + ClassDef *acd=0; + //printf("-------- usage relation %s->%s templ=`%s'\n", + // cd->name().data(),ucd->classDef->name().data(), + // ucd->templSpecifiers.data()); + QCString templSpec = substituteTemplateSpec( + cd,ucd->templSpecifiers); + computeTemplateInstance(cd,ucd->classDef, templSpec, acd,actualArg); + if (acd) + { + addClass(acd,n,EdgeInfo::Black,label,distance,actualArg, + templSpec,base); + } + else + { + //printf("Found label=`%s'\n",label.data()); + addClass(ucd->classDef,n,EdgeInfo::Black,label,distance,0, + templSpec,base); + } } } } @@ -906,6 +1073,11 @@ DotClassGraph::DotClassGraph(ClassDef *cd,GraphType t,int maxRecursionDepth) ); m_usedNodes = new QDict(1009); m_usedNodes->insert(cd->name(),m_startNode); + + ClassSDict::Iterator cli(Doxygen::classSDict); + ClassDef *icd; + for (cli.toFirst();(icd=cli.current());++cli) icd->initTemplateMapping(); + //printf("Root node %s\n",cd->name().data()); if (m_recDepth>0) { diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 6f41dfd..3c9cd3a 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -65,8 +65,8 @@ #define pclose _pclose #endif -ClassList Doxygen::classList; // all documented classes -ClassDict Doxygen::classDict(1009); +ClassSDict Doxygen::classSDict(1009); +ClassList Doxygen::hiddenClasses; NamespaceList Doxygen::namespaceList; // all namespaces NamespaceDict Doxygen::namespaceDict(257); @@ -107,6 +107,7 @@ QIntDict Doxygen::memberDocDict(1009); // dictionary of the member PageInfo *Doxygen::mainPage = 0; QTextStream Doxygen::tagFile; +NamespaceDef *Doxygen::globalScope = new NamespaceDef("",1,""); static StringList inputFiles; static StringDict excludeNameDict(1009); // sections @@ -119,7 +120,7 @@ void clearAll() excludeNameDict.clear(); delete outputList; outputList=0; - Doxygen::classList.clear(); + Doxygen::classSDict.clear(); Doxygen::namespaceList.clear(); Doxygen::pageSDict->clear(); Doxygen::exampleSDict->clear(); @@ -128,7 +129,7 @@ void clearAll() Doxygen::inputNameList.clear(); Doxygen::groupList.clear(); Doxygen::formulaList.clear(); - Doxygen::classDict.clear(); + Doxygen::classSDict.clear(); Doxygen::namespaceDict.clear(); Doxygen::memberNameDict.clear(); Doxygen::functionNameDict.clear(); @@ -143,6 +144,7 @@ void clearAll() Doxygen::formulaNameDict.clear(); Doxygen::tagDestinationDict.clear(); delete Doxygen::mainPage; Doxygen::mainPage=0; + } void statistics() @@ -155,8 +157,8 @@ void statistics() Doxygen::exampleNameDict->statistics(); fprintf(stderr,"--- imageNameDict stats ----\n"); Doxygen::imageNameDict->statistics(); - fprintf(stderr,"--- classDict stats ----\n"); - Doxygen::classDict.statistics(); + //fprintf(stderr,"--- classDict stats ----\n"); + //Doxygen::classSDict.statistics(); fprintf(stderr,"--- namespaceDict stats ----\n"); Doxygen::namespaceDict.statistics(); fprintf(stderr,"--- memberNameDict stats ----\n"); @@ -639,6 +641,62 @@ static bool addNamespace(Entry *root,ClassDef *cd) return FALSE; } +static Definition *findScope(Entry *root,int level=0) +{ + if (root==0) return 0; + //printf("start findScope name=%s\n",root->name.data()); + Definition *result=0; + if (root->section&Entry::SCOPE_MASK) + { + result = findScope(root->parent,level+1); // traverse to the root of the tree + if (result) + { + //printf("Found %s inside %s at level %d\n",root->name.data(),result->name().data(),level); + // TODO: look at template arguments + result = result->findInnerCompound(root->name); + } + else // reached the global scope + { + // TODO: look at template arguments + result = Doxygen::globalScope->findInnerCompound(root->name); + //printf("Found in globalScope %s at level %d\n",result->name().data(),level); + } + } + //printf("end findScope(%s,%d)=%s\n",root->name.data(), + // level,result==0 ? "" : result->name().data()); + return result; +} + +static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n) +{ + //printf("findScopeFromName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data()); + QCString name(n); + if (startScope==0) startScope=Doxygen::globalScope; + int i = name.find("::"); + if (i==-1) + { + return startScope; + } + + QCString scope; + while ((i = name.find("::"))!=-1) + { + int ti = name.find('<'); + if (ti!=-1 && tifindInnerCompound(nestedNameSpecifier); + if (startScope==0) + { + //printf("name %s not found in scope %s\n",nestedNameSpecifier.data(),oldScope->name().data()); + return 0; + } + name = name.right(name.length()-i-2); + } + //printf("findScopeFromName() result=%s\n",startScope ? startScope->name().data() : 0); + return startScope; +} + //---------------------------------------------------------------------- // build a list of all classes mentioned in the documentation // and all classes that have a documentation block before their definition. @@ -737,6 +795,7 @@ static void buildClassList(Entry *root) } else // new class { + ClassDef::CompoundType sec=ClassDef::Class; switch(root->section) { @@ -823,10 +882,27 @@ static void buildClassList(Entry *root) // add class to the list - Doxygen::classList.inSort(cd); //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data()); - //classDict.insert(resolveDefines(fullName),cd); - Doxygen::classDict.insert(fullName,cd); + Doxygen::classSDict.inSort(fullName,cd); + + // also add class to the correct structural context + Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,fullName); + if (d==0) + { + // TODO: Due to the order in which the tag file is written + // a nested class can be found before its parent! + // + //warn(root->fileName,root->startLine, + // "Warning: Internal inconsistency: scope for class %s not " + // "found!\n",fullName.data() + // ); + } + else + { + //printf("****** adding %s to scope %s\n",cd->name().data(),d->name().data()); + d->addInnerCompound(cd); + cd->setOuterScope(d); + } } } } @@ -927,6 +1003,23 @@ static void buildNamespaceList(Entry *root) Doxygen::namespaceList.inSort(nd); Doxygen::namespaceDict.insert(fullName,nd); + // also add namespace to the correct structural context + Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,fullName); + if (d==0) + { + // TODO: Due to the order in which the tag file is written + // a nested class can be found before its parent! + // + //warn(root->fileName,root->startLine, + // "Warning: Internal inconsistency: scope for namespace %s not " + // "found!\n",fullName.data() + // ); + } + else + { + d->addInnerCompound(nd); + nd->setOuterScope(d); + } } } } @@ -2247,8 +2340,11 @@ static void replaceNamespaceAliases(QCString &scope,int i) } -static bool findBaseClassRelation(Entry *root,ClassDef *cd, +static bool findBaseClassRelation( + Entry *root, + ClassDef *cd, BaseInfo *bi, + int isTemplBaseClass, bool insertUndocumented ) { @@ -2416,7 +2512,7 @@ static bool findBaseClassRelation(Entry *root,ClassDef *cd, } } } - if (found) + if (isTemplBaseClass==-1 && found) { Debug::print(Debug::Classes,0," Documented base class `%s'\n",bi->name.data()); // add base class to this class @@ -2427,7 +2523,7 @@ static bool findBaseClassRelation(Entry *root,ClassDef *cd, baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); return TRUE; } - else if (scopeOffset==0 && insertUndocumented) + else if ((scopeOffset==0 && insertUndocumented) || isTemplBaseClass!=-1) { Debug::print(Debug::Classes,0, " Undocumented base class `%s' baseClassName=%s\n", @@ -2441,12 +2537,18 @@ static bool findBaseClassRelation(Entry *root,ClassDef *cd, baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); // the undocumented base was found in this file baseClass->insertUsedFile(root->fileName); + // is this an inherited template argument? + //printf("%s->setIsTemplateBaseClass(%d)\n",baseClass->name().data(),isTemplBaseClass); + baseClass->setIsTemplateBaseClass(isTemplBaseClass); // add class to the list - //classList.inSort(baseClass); - Doxygen::classList.inSort(baseClass); - //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data()); - //classDict.insert(resolveDefines(bi->name),baseClass); - Doxygen::classDict.insert(baseClassName,baseClass); + if (isTemplBaseClass==-1) + { + Doxygen::classSDict.inSort(baseClassName,baseClass); + } + else + { + Doxygen::hiddenClasses.append(baseClass); + } return TRUE; } else @@ -2511,16 +2613,34 @@ static void computeClassRelations(Entry *root) cd->visited=TRUE; // mark class as used if (root->extends->count()>0) // there are base classes { + // The base class could ofcouse also be a non-nested class QList *baseList=root->extends; BaseInfo *bi=baseList->first(); while (bi) // for each base class { + // check if the base class is a template argument + int isTemplBaseClass = -1; + ArgumentList *tl = cd->templateArguments(); + if (tl) + { + ArgumentListIterator ali(*tl); + Argument *arg; + int count=0; + for (ali.toFirst();(arg=ali.current());++ali,++count) + { + if (arg->name==bi->name) // base class is a template argument + { + isTemplBaseClass = count; + break; + } + } + } // find a documented base class in the correct scope - if (!findBaseClassRelation(root,cd,bi,FALSE)) + if (!findBaseClassRelation(root,cd,bi,isTemplBaseClass,FALSE)) { // no documented base class -> try to find an undocumented one - findBaseClassRelation(root,cd,bi,TRUE); + findBaseClassRelation(root,cd,bi,isTemplBaseClass,TRUE); } bi=baseList->next(); } @@ -2550,11 +2670,11 @@ static void computeClassRelations(Entry *root) static void computeMemberReferences() { - ClassDef *cd=Doxygen::classList.first(); - while (cd) + ClassSDict::Iterator cli(Doxygen::classSDict); + ClassDef *cd=0; + for (cli.toFirst();(cd=cli.current());++cli) { cd->computeAnchors(); - cd=Doxygen::classList.next(); } FileName *fn=Doxygen::inputNameList.first(); while (fn) @@ -2585,14 +2705,14 @@ static void computeMemberReferences() static void addTodoTestBugReferences() { - ClassDef *cd=Doxygen::classList.first(); - while (cd) + ClassSDict::Iterator cli(Doxygen::classSDict); + ClassDef *cd=0; + for (cli.toFirst();(cd=cli.current());++cli) { addRefItem(cd->todoId(),cd->testId(),cd->bugId(), theTranslator->trClass(TRUE,TRUE), cd->getOutputFileBase(),cd->name() ); - cd=Doxygen::classList.next(); } FileName *fn=Doxygen::inputNameList.first(); while (fn) @@ -4115,39 +4235,41 @@ static void findEnums(Entry *root) { MemberNameIterator fmni(*fmn); MemberDef *fmd; - for (fmni.toFirst(); - (fmd=fmni.current()) && fmd->isEnumValue(); - ++fmni - ) // search for the scope with the right name + for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni) { - if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') + if (fmd->isEnumValue()) { - NamespaceDef *fnd=fmd->getNamespaceDef(); - if (fnd==nd) // enum value is inside a namespace + if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') { - md->insertEnumField(fmd); - fmd->setEnumScope(md); + NamespaceDef *fnd=fmd->getNamespaceDef(); + if (fnd==nd) // enum value is inside a namespace + { + md->insertEnumField(fmd); + fmd->setEnumScope(md); + } } - } - else if (isGlobal) - { - FileDef *ffd=fmd->getFileDef(); - if (ffd==fd) // enum value has file scope + else if (isGlobal) { - md->insertEnumField(fmd); - fmd->setEnumScope(md); + FileDef *ffd=fmd->getFileDef(); + if (ffd==fd) // enum value has file scope + { + md->insertEnumField(fmd); + fmd->setEnumScope(md); + } } - } - else - { - ClassDef *fcd=fmd->getClassDef(); - if (fcd==cd) // enum value is inside a class + else { - md->insertEnumField(fmd); // add field def to list - fmd->setEnumScope(md); // cross ref with enum name + ClassDef *fcd=fmd->getClassDef(); + if (fcd==cd) // enum value is inside a class + { + //printf("Inserting enum field %s in enum scope %s\n", + // fmd->name().data(),md->name().data()); + md->insertEnumField(fmd); // add field def to list + fmd->setEnumScope(md); // cross ref with enum name + } } - } - } + } + } } } } @@ -4373,7 +4495,7 @@ static void computeMemberRelations() static void computeClassImplUsageRelations() { ClassDef *cd; - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); for (;(cd=cli.current());++cli) { cd->determineImplUsageRelation(); @@ -4388,7 +4510,7 @@ static void buildCompleteMemberLists() { ClassDef *cd; // merge the member list of base classes into the inherited classes. - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); for (cli.toFirst();(cd=cli.current());++cli) { if (!cd->isReference() && // not an external class @@ -4401,7 +4523,7 @@ static void buildCompleteMemberLists() // now sort the member list of all classes. for (cli.toFirst();(cd=cli.current());++cli) { - cd->memberNameInfoList()->sort(); + cd->memberNameInfoSDict()->sort(); } } @@ -4463,7 +4585,7 @@ static void generateFileDocs() static void addSourceReferences() { // add source references for class definitions - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); ClassDef *cd=0; for (cli.toFirst();(cd=cli.current());++cli) { @@ -4568,7 +4690,7 @@ static void generateClassDocs() msg("Generating example index...\n"); } - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); for ( ; cli.current() ; ++cli ) { ClassDef *cd=cli.current(); @@ -4621,7 +4743,7 @@ static void inheritDocumentation() static void addMembersToMemberGroup() { // for each class - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); ClassDef *cd; for ( ; (cd=cli.current()) ; ++cli ) { @@ -4660,7 +4782,7 @@ static void addMembersToMemberGroup() static void distributeMemberGroupDocumentation() { // for each class - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); ClassDef *cd; for ( ; (cd=cli.current()) ; ++cli ) { @@ -4923,7 +5045,7 @@ static void buildPackageList(Entry *root) static void addClassesToPackages() { ClassDef *cd; - ClassListIterator cli(Doxygen::classList); + ClassSDict::Iterator cli(Doxygen::classSDict); for (;(cd=cli.current());++cli) { PackageDef *pd = cd->packageDef(); @@ -4974,7 +5096,7 @@ static void generatePageDocs() if (!pi->inGroup && !pi->isReference()) { msg("Generating docs for page %s...\n",pi->name.data()); - outputList->disable(OutputGenerator::Man); + //outputList->disable(OutputGenerator::Man); QCString pageName; if (Config_getBool("CASE_SENSE_NAMES")) pageName=pi->name.copy(); @@ -4982,19 +5104,29 @@ static void generatePageDocs() pageName=pi->name.lower(); startFile(*outputList,pageName,pi->title); + + startFile(*outputList,pageName,pi->title); + + // save old generator state and write title only to Man generator + outputList->pushGeneratorState(); + outputList->disableAllBut(OutputGenerator::Man); + outputList->startTitleHead(pageName); + outputList->endTitleHead(pageName, pageName); + outputList->popGeneratorState(); + SectionInfo *si=0; if (!pi->title.isEmpty() && !pi->name.isEmpty() && (si=Doxygen::sectionDict.find(pi->name))!=0) { - outputList->startSection(si->label,si->title,FALSE); + outputList->startSection(si->label,si->title,si->type==SectionInfo::Subsection); outputList->docify(si->title); - outputList->endSection(si->label,FALSE); + outputList->endSection(si->label,si->type==SectionInfo::Subsection); } outputList->startTextBlock(); parseDoc(*outputList,pi->defFileName,pi->defLine,0,0,pi->doc); outputList->endTextBlock(); endFile(*outputList); - outputList->enable(OutputGenerator::Man); + //outputList->enable(OutputGenerator::Man); if (!Config_getString("GENERATE_TAGFILE").isEmpty() && pi->name!="todo" && pi->name!="test") { @@ -5287,7 +5419,8 @@ static bool openOutputFile(const char *outFile,QFile &f) * If the \a shortList parameter is TRUE a configuration file without * comments will be generated. */ -static void generateConfigFile(const char *configFile,bool shortList) +static void generateConfigFile(const char *configFile,bool shortList, + bool updateOnly=FALSE) { QFile f; bool fileOpened=openOutputFile(configFile,f); @@ -5297,13 +5430,20 @@ static void generateConfigFile(const char *configFile,bool shortList) Config::instance()->writeTemplate(&f,shortList); if (!writeToStdout) { - msg("\n\nConfiguration file `%s' created.\n\n",configFile); - msg("Now edit the configuration file and enter\n\n"); - if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile")) - msg(" doxygen %s\n\n",configFile); + if (!updateOnly) + { + msg("\n\nConfiguration file `%s' created.\n\n",configFile); + msg("Now edit the configuration file and enter\n\n"); + if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile")) + msg(" doxygen %s\n\n",configFile); + else + msg(" doxygen\n\n"); + msg("to generate the documentation for your project\n\n"); + } else - msg(" doxygen\n\n"); - msg("to generate the documentation for your project\n\n"); + { + msg("\n\nConfiguration file `%s' updated.\n\n",configFile); + } } } else @@ -6014,7 +6154,7 @@ void readConfiguration(int argc, char **argv) if (updateConfig) { - generateConfigFile(configName,shortList); + generateConfigFile(configName,shortList,TRUE); exit(1); } diff --git a/src/doxygen.h b/src/doxygen.h index ed661c4..f81241a 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -40,9 +40,15 @@ class PageInfo; typedef QList StringList; typedef QDict FileDict; -typedef QDict StringDict; typedef QDict GroupDict; +class StringDict : public QDict +{ + public: + StringDict(uint size=17) : QDict(size) {} + virtual ~StringDict() {} +}; + extern QCString spaces; /*! \brief This class serves as a namespace for global variables used by doxygen. @@ -52,8 +58,8 @@ extern QCString spaces; class Doxygen { public: - static ClassList classList; - static ClassDict classDict; + static ClassSDict classSDict; + static ClassList hiddenClasses; static PageSDict *exampleSDi