From eaf8edbac7e6a1873aa5c4ff0df063cd367351d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Nov 2017 13:36:12 +0100 Subject: Propagate language information to all XML elements. This is based on work done in 141dbfd5a4f79c98da14a1b414c6db4e1b34618b through ed9acb6e1bb81a2eec334180f7b8c1bf0598b444 and makes a few behavioral changes to it. There's a new attribute called `filename` and the `language` was removed, because it could provide misleading information. This allows for more flexibility on the user side. In particular: * For historical reasons, `*.txt` files are marked by Doxygen as C++ (see https://bugzilla.gnome.org/show_bug.cgi?id=760836 for details). In particular, code snippet included from a CMakeLists.txt file would be marked and highlighted as C++. So in this case, the language attribute would be very misleading. * Doxygen is aware only of a very small subset of languages and thus a lot of information can be lost when relying on its extension-to-language-name conversion -- in particular, all extensions that are not recognized are assumed to be C++. On the other hand, putting more effort into its language detection algorithms is not worth the time, as there will always be new languages that fail to detect. So let's leave that on the user of the XML output instead. * Using just file extension is not enough, it has to be a full filename. For example, `*.txt` can be either a plain text file or a `CMakeLists.txt`. * The path is not stripped from the filename, as it also may contain additional information that helps to detect the language better. In addition to that, filenames of code snippets included via the \include command and related are propagated to the element as well. With this change, (1) code snippets using simply \code some code \endcode will not produce any `filename` attribute and it's up to the user what to do -- assume C++, detect language from contents or not highlight anything. some code (2) Code snippets using \code{.cmake} some code \endcode will produce the following: some code (3) And finally, \include, \dontinclude and related \skip, \skipline etc. commands \include path/to/some-file.py will produce some code The tests were updated to check all three cases. On the user side, when using Pygments for example, it's then just a matter of calling pygments.lexers.find_lexer_class_for_filename() with value of the `filename` attribute value and optionally also the code snippet for additional language analysis. --- src/docparser.cpp | 3 +++ src/docparser.h | 2 ++ src/xmldocvisitor.cpp | 16 ++++++++++------ templates/xml/compound.xsd | 2 +- testing/014/indexpage.xml | 11 +++++++++-- testing/014_code.dox | 4 ++++ testing/021/indexpage.xml | 2 +- testing/025/example_test_8cpp-example.xml | 2 +- testing/032/indexpage.xml | 2 +- testing/049/indexpage.xml | 2 +- 10 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/docparser.cpp b/src/docparser.cpp index 5bb28ea..eac6e97 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -104,6 +104,7 @@ static QCString g_exampleName; static SectionDict * g_sectionDict; static QCString g_searchUrl; +static QCString g_includeFileName; static QCString g_includeFileText; static uint g_includeFileOffset; static uint g_includeFileLength; @@ -1917,6 +1918,7 @@ void DocInclude::parse() // fall through case DontInclude: readTextFileByName(m_file,m_text); + g_includeFileName = m_file; g_includeFileText = m_text; g_includeFileOffset = 0; g_includeFileLength = m_text.length(); @@ -1954,6 +1956,7 @@ void DocInclude::parse() void DocIncOperator::parse() { + m_includeFileName = g_includeFileName; const char *p = g_includeFileText; uint l = g_includeFileLength; uint o = g_includeFileOffset; diff --git a/src/docparser.h b/src/docparser.h index f5167dc..02c727d 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -541,6 +541,7 @@ class DocIncOperator : public DocNode void markLast(bool v=TRUE) { m_isLast = v; } bool isExample() const { return m_isExample; } QCString exampleFile() const { return m_exampleFile; } + QCString includeFileName() const { return m_includeFileName; } void parse(); private: @@ -552,6 +553,7 @@ class DocIncOperator : public DocNode bool m_isLast; bool m_isExample; QCString m_exampleFile; + QCString m_includeFileName; }; /** Node representing an item of a cross-referenced list */ diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 5789283..55c2b38 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -211,7 +211,11 @@ void XmlDocVisitor::visit(DocVerbatim *s) switch(s->type()) { case DocVerbatim::Code: // fall though - m_t << ""; + m_t << "language().isEmpty()) + m_t << " filename=\"" << lang << "\">"; + else + m_t << ">"; Doxygen::parserManager->getParser(lang) ->parseCode(m_ci,s->context(),s->text(),langExt, s->isExample(),s->exampleFile()); @@ -264,7 +268,7 @@ void XmlDocVisitor::visit(DocInclude *inc) { case DocInclude::IncWithLines: { - m_t << ""; + m_t << "file() << "\">"; QFileInfo cfi( inc->file() ); FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() ); Doxygen::parserManager->getParser(inc->extension()) @@ -284,7 +288,7 @@ void XmlDocVisitor::visit(DocInclude *inc) } break; case DocInclude::Include: - m_t << ""; + m_t << "file() << "\">"; Doxygen::parserManager->getParser(inc->extension()) ->parseCode(m_ci,inc->context(), inc->text(), @@ -318,7 +322,7 @@ void XmlDocVisitor::visit(DocInclude *inc) m_t << ""; break; case DocInclude::Snippet: - m_t << ""; + m_t << "file() << "\">"; Doxygen::parserManager->getParser(inc->extension()) ->parseCode(m_ci, inc->context(), @@ -331,7 +335,7 @@ void XmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::SnipWithLines: { - m_t << ""; + m_t << "file() << "\">"; QFileInfo cfi( inc->file() ); FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() ); Doxygen::parserManager->getParser(inc->extension()) @@ -367,7 +371,7 @@ void XmlDocVisitor::visit(DocIncOperator *op) { if (!m_hide) { - m_t << ""; + m_t << "includeFileName() << "\">"; } pushEnabled(); m_hide = TRUE; diff --git a/templates/xml/compound.xsd b/templates/xml/compound.xsd index 43cc897..8affc20 100644 --- a/templates/xml/compound.xsd +++ b/templates/xml/compound.xsd @@ -264,7 +264,7 @@ - + diff --git a/testing/014/indexpage.xml b/testing/014/indexpage.xml index ad35261..e677e24 100644 --- a/testing/014/indexpage.xml +++ b/testing/014/indexpage.xml @@ -5,7 +5,7 @@ My Project - + #commentinPython @@ -25,7 +25,7 @@ - + //commentinacodeblock @@ -37,6 +37,13 @@ + + + + //implicitcodelanguage + + + diff --git a/testing/014_code.dox b/testing/014_code.dox index 871a44c..56597cc 100644 --- a/testing/014_code.dox +++ b/testing/014_code.dox @@ -11,4 +11,8 @@ * // comment in a code block * class Cpp {}; * \endcode + * + * \code + * // implicit code language + * \endcode */ diff --git a/testing/021/indexpage.xml b/testing/021/indexpage.xml index 20e1ad2..9205dd6 100644 --- a/testing/021/indexpage.xml +++ b/testing/021/indexpage.xml @@ -4,7 +4,7 @@ index My Project - Our main function starts like this: voidmain(){ First we create a object t of the Test class. Testt; Then we call the example member function t.example(); After that our little test routine ends. } + Our main function starts like this: voidmain(){ First we create a object t of the Test class. Testt; Then we call the example member function t.example(); After that our little test routine ends. } diff --git a/testing/025/example_test_8cpp-example.xml b/testing/025/example_test_8cpp-example.xml index 6c0ce90..96a1cd7 100644 --- a/testing/025/example_test_8cpp-example.xml +++ b/testing/025/example_test_8cpp-example.xml @@ -4,7 +4,7 @@ example_test.cpp This is an example of how to use the Test class. - More details about this example. voidmain(){Testt;t.example();} + More details about this example. voidmain(){Testt;t.example();} diff --git a/testing/032/indexpage.xml b/testing/032/indexpage.xml index ba401c8..3a25272 100644 --- a/testing/032/indexpage.xml +++ b/testing/032/indexpage.xml @@ -4,7 +4,7 @@ index My Project - Some text. voidmain(){Testt;t.example();} More text. voidmain(){Testt;t.example();} End. + Some text. voidmain(){Testt;t.example();} More text. voidmain(){Testt;t.example();} End. diff --git a/testing/049/indexpage.xml b/testing/049/indexpage.xml index a6c9b97..461a174 100644 --- a/testing/049/indexpage.xml +++ b/testing/049/indexpage.xml @@ -4,7 +4,7 @@ index My Project - A bubble sort algorithm First get the inputs for(i=0;i<n;i++){printf("Array[%d]=",i);scanf("%d",&arr[i]);}Then do the bubbling for(i=0;i<n;i++){for(j=0;j<n-i-1;j++){if(arr[j]>arr[j+1])//SwappingConditionisChecked{temp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}}}Then write the result for(i=0;i<n;i++){printf("%4d",arr[i]);} + A bubble sort algorithm First get the inputs for(i=0;i<n;i++){printf("Array[%d]=",i);scanf("%d",&arr[i]);}Then do the bubbling for(i=0;i<n;i++){for(j=0;j<n-i-1;j++){if(arr[j]>arr[j+1])//SwappingConditionisChecked{temp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}}}Then write the result for(i=0;i<n;i++){printf("%4d",arr[i]);} -- cgit v0.12