diff options
author | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2015-11-05 00:00:07 +0100 |
---|---|---|
committer | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2015-11-05 00:15:52 +0100 |
commit | 2e5be58e7c81436139785074ee2cc6991b6f9e24 (patch) | |
tree | 35c1cc308aeefcc222a58763c47d6fe5b9081dad /compilerplugins | |
parent | 0305078a6a5d4d2b0ef64996c056d86b5eda42ce (diff) |
complete initial compiler plugin for the ServiceDocumenter
- this creates a set of static html-meta-redirect-pages linking the UNO
implementation name to its C++ class, while doing a clang compile from
scratch
- the output is written to $(WORKDIR)/ServiceImplementations
- still quite some corner cases missing, e.g:
- anonymous namespaces
- non-trivial getImplementationName() functions
Change-Id: I19a0e8a3901277dc3811eb428cac9d00737f14a9
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/getimplementationname.cxx | 98 |
1 files changed, 88 insertions, 10 deletions
diff --git a/compilerplugins/clang/getimplementationname.cxx b/compilerplugins/clang/getimplementationname.cxx index 3b999c5849f4..ad2b93a7d939 100644 --- a/compilerplugins/clang/getimplementationname.cxx +++ b/compilerplugins/clang/getimplementationname.cxx @@ -7,9 +7,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// only compile this on unixy system +// as we dont want to bother with x-platform system()/mkdir() +#if defined(__unix__) +// only compile this on clang 3.7 or higher, which is known to work +// there were problems on clang 3.5 at least +#if (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 7)) #include <cassert> - +#include <stdlib.h> +#include <string> +#include <iostream> +#include <fstream> +#include <regex> #include "plugin.hxx" +#include "clang/Frontend/CompilerInstance.h" namespace { @@ -58,9 +69,12 @@ class GetImplementationName: public loplugin::Plugin { public: - explicit GetImplementationName(InstantiationData const & data): Plugin(data) + explicit GetImplementationName(InstantiationData const & data) + : Plugin(data) + , m_Outdir(initOutdir()) + , m_OutdirCreated(false) + , m_Srcdir(initSrcdir()) {} - void run() override; bool VisitCXXMethodDecl(clang::CXXMethodDecl const * decl); @@ -70,6 +84,28 @@ private: bool returnsStringConstant( FunctionDecl const * decl, clang::StringRef * string); + + void ensureOutdirCreated() + { + if(m_OutdirCreated) + return; + std::string cmd("mkdir -p "); + cmd += "\"" + m_Outdir + "\""; + if(system(cmd.c_str()) != 0) { + report( + clang::DiagnosticsEngine::Error, + "Error creating ServiceImplementations output dir \"%0\".") + << m_Outdir; + } + m_OutdirCreated = true; + } + + void generateOutput(FunctionDecl const * decl, const std::string unoimpl, const std::string cppclass); + std::string initOutdir(); + std::string initSrcdir(); + const std::string m_Outdir; + bool m_OutdirCreated; + const std::string m_Srcdir; }; void GetImplementationName::run() { @@ -92,19 +128,15 @@ bool GetImplementationName::VisitCXXMethodDecl( { return true; } - clang::StringRef str; - if (!returnsStringConstant(decl, &str)) { + clang::StringRef unoimpl; + if (!returnsStringConstant(decl, &unoimpl)) { report( clang::DiagnosticsEngine::Warning, "cannot determine returned string", decl->getLocation()) << decl->getSourceRange(); return true; } - report( - clang::DiagnosticsEngine::Warning, "\"%0\" implemented by %1", - decl->getLocation()) - << str << decl->getParent()->getQualifiedNameAsString() - << decl->getSourceRange(); + generateOutput(decl, unoimpl.str(), decl->getParent()->getQualifiedNameAsString()); return true; } @@ -221,8 +253,54 @@ bool GetImplementationName::returnsStringConstant( } } +void GetImplementationName::generateOutput(FunctionDecl const * decl, const std::string unoimpl, const std::string cppclass) { + ensureOutdirCreated(); + clang::SourceManager& sm(compiler.getSourceManager()); + const std::string absfilename(sm.getFilename(decl->getSourceRange().getBegin()).str()); + if(absfilename.length() <= m_Srcdir.length()) + return; + const std::string filename(absfilename.substr(m_Srcdir.length()+1)); + const std::regex moduleregex("^\\w+"); + std::smatch modulematch; + std::regex_search(filename, modulematch, moduleregex); + if(modulematch.empty()) + return; + const std::string module(modulematch[0]); + const std::regex doublecolonregex("::"); + const std::string cppclassweb(std::regex_replace(cppclass, doublecolonregex, "_1_1")); + std::ofstream redirectfile(m_Outdir + "/" + unoimpl + ".html"); + redirectfile << "<meta http-equiv=\"refresh\" content=\"0; URL=http://docs.libreoffice.org/" << module << "/html/class" << cppclassweb << "\">\n"; + redirectfile.close(); +} + +std::string GetImplementationName::initOutdir() { +{ + char* pWorkdir = getenv("WORKDIR"); + if(pWorkdir) { + std::string result(pWorkdir); + result += "/ServiceImplementations"; + return result; + } + report( + clang::DiagnosticsEngine::Error, "WORKDIR unset, dont know where to write service implementation info."); + return std::string(); + } +} + +std::string GetImplementationName::initSrcdir() { +{ + char* pSrcdir = getenv("SRCDIR"); + if(!pSrcdir) { + report( + clang::DiagnosticsEngine::Error, "SRCDIR unset, dont know where the source base is."); + } + return std::string(pSrcdir); + } +} loplugin::Plugin::Registration<GetImplementationName> X( "getimplementationname"); } +#endif +#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |