From 03d4f7b9924d9fa767411b8fccd3607ce962275d Mon Sep 17 00:00:00 2001 From: Francesco Montorsi Date: Thu, 27 Mar 2008 20:57:05 +0000 Subject: [PATCH] add 'availability' infos to both wxMethod and wxClass: in this way ifacecheck does not warn about methods documented to be available only for port X, which are missing from the gcc XML, if the gcc XML was produced for a port different than X; this requires @onlyfor ALIAS to output tags in the XML output git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52863 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/doxygen/Doxyfile_inc | 10 +- utils/ifacecheck/rungccxml.sh.in | 6 +- utils/ifacecheck/src/ifacecheck.cpp | 56 ++++++--- utils/ifacecheck/src/xmlparser.cpp | 185 ++++++++++++++++++---------- utils/ifacecheck/src/xmlparser.h | 65 ++++++++-- 5 files changed, 228 insertions(+), 94 deletions(-) diff --git a/docs/doxygen/Doxyfile_inc b/docs/doxygen/Doxyfile_inc index 2fb298c095..b487efb308 100644 --- a/docs/doxygen/Doxyfile_inc +++ b/docs/doxygen/Doxyfile_inc @@ -77,10 +77,12 @@ ALIASES += nativeimpl{3}="
Implementations: & ALIASES += nativeimpl{4}="
Implementations:  native under \ref page_port_\1, \ref page_port_\2, \ref page_port_\3, \ref page_port_\4 ports; a generic implementation is used elsewhere.
" # onlyfor infos: -ALIASES += onlyfor{1}="
Availability:  only available for the \ref page_port_\1 port.
" -ALIASES += onlyfor{2}="
Availability:  only available for the \ref page_port_\1, \ref page_port_\2 ports.
" -ALIASES += onlyfor{3}="
Availability:  only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3 ports.
" -ALIASES += onlyfor{4}="
Availability:  only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3, \ref page_port_\4 ports.
" +# NOTE: we need to be able to retrieve these infos also from the XML output, thus +# we use the \xmlonly and \endxmlonly commands to include custom XML tags +ALIASES += onlyfor{1}="
Availability:  only available for the \ref page_port_\1 port.
\xmlonly \1 \endxmlonly" +ALIASES += onlyfor{2}="
Availability:  only available for the \ref page_port_\1, \ref page_port_\2 ports.
\xmlonly \1,\2 \endxmlonly" +ALIASES += onlyfor{3}="
Availability:  only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3 ports.
\xmlonly \1,\2,\3 \endxmlonly" +ALIASES += onlyfor{4}="
Availability:  only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3, \ref page_port_\4 ports.
\xmlonly \1,\2,\3,\4 \endxmlonly" # creates appearance section: this should be used for all main GUI controls ALIASES += appearance{1}="@htmlonly
Appearance:
wxMSW appearancewxGTK appearancewxMac appearance
wxMSW appearancewxGTK appearancewxMac appearance
@endhtmlonly" diff --git a/utils/ifacecheck/rungccxml.sh.in b/utils/ifacecheck/rungccxml.sh.in index fcd58240cc..c18eae5ae9 100755 --- a/utils/ifacecheck/rungccxml.sh.in +++ b/utils/ifacecheck/rungccxml.sh.in @@ -34,7 +34,7 @@ me=$(basename $0) path=${0%%/$me} current=$(pwd) # current path -gccxmloutput="$current/$gccxmloutput" +#gccxmloutput="$current/$gccxmloutput" cd @top_srcdir@/include # go to wx include folder @@ -61,13 +61,13 @@ flags=`echo "$flags" | sed -e 's/-pthread//g' | sed -e 's/__WXDEBUG__//g'` flags="-I . -I @top_srcdir@/include $flags -D__WXDEBUG__ -D__WX@TOOLKIT@__ -DWXBUILDING $allheaders" # run gccxml with the same flag used for the real compilation of wx sources: -echo "Running gccxml on the $allheaders file..." +echo "Running gccxml on the $allheaders file... results in $gccxmloutput" if [[ -f "$gccxmloutput" ]]; then rm $gccxmloutput; fi gccxml $flags -fxml=$gccxmloutput # now get the list of the #defined values for wx headers, so that the result # can be passed to ifacecheck to aid the comparison -echo "Running gccxml's preprocessor on the $allheaders file..." +echo "Running gccxml's preprocessor on the $allheaders file... results in $preprocoutput" gccxml -E -dM $flags >$preprocoutput # cleanup diff --git a/utils/ifacecheck/src/ifacecheck.cpp b/utils/ifacecheck/src/ifacecheck.cpp index d2c63869e6..a8ce9b2bc6 100644 --- a/utils/ifacecheck/src/ifacecheck.cpp +++ b/utils/ifacecheck/src/ifacecheck.cpp @@ -93,8 +93,8 @@ public: } protected: - wxXmlGccInterface m_api; // "real" headers API - wxXmlDoxygenInterface m_interface; // doxygen-commented headers API + wxXmlGccInterface m_gccInterface; // "real" headers API + wxXmlDoxygenInterface m_doxyInterface; // doxygen-commented headers API // was the MODIFY_SWITCH passed? bool m_modify; @@ -133,21 +133,21 @@ int IfaceCheckApp::OnRun() } // in any case set basic std preprocessor #defines: - m_interface.AddPreprocessorValue("NULL", "0"); + m_doxyInterface.AddPreprocessorValue("NULL", "0"); // parse the two XML files which contain the real and the doxygen interfaces // for wxWidgets API: - if (!m_api.Parse(parser.GetParam(0)) || - !m_interface.Parse(parser.GetParam(1))) + if (!m_gccInterface.Parse(parser.GetParam(0)) || + !m_doxyInterface.Parse(parser.GetParam(1))) return 1; if (parser.Found(DUMP_SWITCH)) { LogMessage("Dumping real API to '%s'...", API_DUMP_FILE); - m_api.Dump(API_DUMP_FILE); + m_gccInterface.Dump(API_DUMP_FILE); LogMessage("Dumping interface API to '%s'...", INTERFACE_DUMP_FILE); - m_interface.Dump(INTERFACE_DUMP_FILE); + m_doxyInterface.Dump(INTERFACE_DUMP_FILE); } else { @@ -195,7 +195,7 @@ void IfaceCheckApp::ShowProgress() bool IfaceCheckApp::Compare() { - const wxClassArray& interface = m_interface.GetClasses(); + const wxClassArray& interface = m_doxyInterface.GetClasses(); const wxClass* c; wxClassPtrArray api; int mcount = 0, ccount = 0; @@ -208,6 +208,18 @@ bool IfaceCheckApp::Compare() for (unsigned int i=0; i0) { @@ -242,9 +254,9 @@ bool IfaceCheckApp::Compare() } LogMessage("%d methods (%.1f%%) of the interface headers do not exist in the real headers", - mcount, (float)(100.0 * mcount/m_interface.GetMethodCount())); + mcount, (float)(100.0 * mcount/m_doxyInterface.GetMethodCount())); LogMessage("%d classes (%.1f%%) of the interface headers do not exist in the real headers", - ccount, (float)(100.0 * ccount/m_interface.GetClassesCount())); + ccount, (float)(100.0 * ccount/m_doxyInterface.GetClassesCount())); return true; } @@ -270,6 +282,18 @@ int IfaceCheckApp::CompareClasses(const wxClass* iface, const wxClassPtrArray& a const wxMethod& m = iface->GetMethod(i); int matches = 0; + // only compare the methods which are available for the port + // for which the gcc XML was produced + if (m.GetAvailability() != wxPORT_UNKNOWN && + (m.GetAvailability() & m_gccInterface.GetInterfacePort()) == 0) { + + if (g_verbose) + LogMessage("skipping method '%s' since it's not available for the %s port.", + m.GetAsString(), m_gccInterface.GetInterfacePortName()); + + continue; // skip this method + } + // search in the methods of the api classes provided for (unsigned int j=0; jGetMethodCount(); j++) @@ -529,7 +553,7 @@ bool IfaceCheckApp::ParsePreprocessorOutput(const wxString& filename) defval = defval.Mid(1, defval.Len()-2); // store this pair in the doxygen interface, where it can be useful - m_interface.AddPreprocessorValue(defname, defval); + m_doxyInterface.AddPreprocessorValue(defname, defval); useful++; } @@ -542,9 +566,9 @@ bool IfaceCheckApp::ParsePreprocessorOutput(const wxString& filename) void IfaceCheckApp::PrintStatistics(long secs) { LogMessage("wx real headers contains declaration of %d classes (%d methods)", - m_api.GetClassesCount(), m_api.GetMethodCount()); + m_gccInterface.GetClassesCount(), m_gccInterface.GetMethodCount()); LogMessage("wx interface headers contains declaration of %d classes (%d methods)", - m_interface.GetClassesCount(), m_interface.GetMethodCount()); + m_doxyInterface.GetClassesCount(), m_doxyInterface.GetMethodCount()); LogMessage("total processing took %d seconds.", secs); } diff --git a/utils/ifacecheck/src/xmlparser.cpp b/utils/ifacecheck/src/xmlparser.cpp index 69d5684f1d..43892d970d 100644 --- a/utils/ifacecheck/src/xmlparser.cpp +++ b/utils/ifacecheck/src/xmlparser.cpp @@ -927,6 +927,121 @@ bool wxXmlGccInterface::ParseMethod(const wxXmlNode *p, } + +// ---------------------------------------------------------------------------- +// wxXmlDoxygenInterface global helpers +// ---------------------------------------------------------------------------- + +static wxString GetTextFromChildren(const wxXmlNode *n) +{ + wxString text; + + // consider the tree + // + // this is a string + // + // + // |- + // | |- this + // |- is a + // |- + // |- string + // + // unlike wxXmlNode::GetNodeContent() which would return " is a " + // this function returns "this is a string" + + wxXmlNode *ref = n->GetChildren(); + while (ref) { + if (ref->GetType() == wxXML_ELEMENT_NODE) + text += ref->GetNodeContent(); + else if (ref->GetType() == wxXML_TEXT_NODE) + text += ref->GetContent(); + else + LogWarning("Unexpected node type while getting text from '%s' node", n->GetName()); + + ref = ref->GetNext(); + } + + return text; +} + +static bool HasTextNodeContaining(const wxXmlNode *parent, const wxString& name) +{ + if (!parent) + return false; + + wxXmlNode *p = parent->GetChildren(); + while (p) + { + switch (p->GetType()) + { + case wxXML_TEXT_NODE: + if (p->GetContent() == name) + return true; + break; + + case wxXML_ELEMENT_NODE: + // recurse into this node... + if (HasTextNodeContaining(p, name)) + return true; + break; + + default: + // skip it + break; + } + + p = p->GetNext(); + } + + return false; +} + +static const wxXmlNode* FindNodeNamed(const wxXmlNode* parent, const wxString& name) +{ + if (!parent) + return NULL; + + const wxXmlNode *p = parent->GetChildren(); + while (p) + { + if (p->GetName() == name) + return p; // found! + + // search recursively in the children of this node + const wxXmlNode *ret = FindNodeNamed(p, name); + if (ret) + return ret; + + p = p->GetNext(); + } + + return NULL; +} + +int GetAvailabilityFor(const wxXmlNode *node) +{ + // identify custom XML tags + const wxXmlNode* onlyfor = FindNodeNamed(node, "onlyfor"); + if (!onlyfor) + return wxPORT_UNKNOWN; + + wxArrayString ports = wxSplit(onlyfor->GetNodeContent(), ','); + int nAvail = wxPORT_UNKNOWN; + for (unsigned int i=0; i < ports.GetCount(); i++) + { + if (!ports[i].StartsWith("wx")) { + LogError("unexpected port ID '%s'", ports[i]); + return false; + } + + nAvail |= wxPlatformInfo::GetPortId(ports[i].Mid(2)); + } + + return nAvail; +} + + // ---------------------------------------------------------------------------- // wxXmlDoxygenInterface // ---------------------------------------------------------------------------- @@ -1059,6 +1174,11 @@ bool wxXmlDoxygenInterface::ParseCompoundDefinition(const wxString& filename) klass.SetHeader(subchild->GetNodeContent()); }*/ + else if (subchild->GetName() == "detaileddescription") + { + // identify custom XML tags + klass.SetAvailability(GetAvailabilityFor(subchild)); + } subchild = subchild->GetNext(); } @@ -1080,68 +1200,6 @@ bool wxXmlDoxygenInterface::ParseCompoundDefinition(const wxString& filename) return true; } -static wxString GetTextFromChildren(const wxXmlNode *n) -{ - wxString text; - - // consider the tree - // - // this is a string - // - // - // |- - // | |- this - // |- is a - // |- - // |- string - // - // unlike wxXmlNode::GetNodeContent() which would return " is a " - // this function returns "this is a string" - - wxXmlNode *ref = n->GetChildren(); - while (ref) { - if (ref->GetType() == wxXML_ELEMENT_NODE) - text += ref->GetNodeContent(); - else if (ref->GetType() == wxXML_TEXT_NODE) - text += ref->GetContent(); - else - LogWarning("Unexpected node type while getting text from '%s' node", n->GetName()); - - ref = ref->GetNext(); - } - - return text; -} - -static bool HasTextNodeContaining(const wxXmlNode *parent, const wxString& name) -{ - wxXmlNode *p = parent->GetChildren(); - while (p) - { - switch (p->GetType()) - { - case wxXML_TEXT_NODE: - if (p->GetContent() == name) - return true; - break; - - case wxXML_ELEMENT_NODE: - // recurse into this node... - if (HasTextNodeContaining(p, name)) - return true; - break; - - default: - // skip it - break; - } - - p = p->GetNext(); - } - - return false; -} - bool wxXmlDoxygenInterface::ParseMethod(const wxXmlNode* p, wxMethod& m, wxString& header) { wxArgumentTypeArray args; @@ -1202,6 +1260,9 @@ bool wxXmlDoxygenInterface::ParseMethod(const wxXmlNode* p, wxMethod& m, wxStrin // Doxygen outputs somewhere nested inside // a Deprecated tag. m.SetDeprecated(HasTextNodeContaining(child, "Deprecated")); + + // identify custom XML tags + m.SetAvailability(GetAvailabilityFor(child)); } child = child->GetNext(); diff --git a/utils/ifacecheck/src/xmlparser.h b/utils/ifacecheck/src/xmlparser.h index 6e1de99a42..a593819279 100644 --- a/utils/ifacecheck/src/xmlparser.h +++ b/utils/ifacecheck/src/xmlparser.h @@ -114,7 +114,8 @@ class wxMethod { public: wxMethod() - { m_bConst=m_bVirtual=m_bPureVirtual=m_bStatic=m_bDeprecated=false; m_nLine=-1; } + { m_bConst=m_bVirtual=m_bPureVirtual=m_bStatic=m_bDeprecated=false; + m_nLine=-1; m_nAvailability=wxPORT_UNKNOWN; } wxMethod(const wxType& rettype, const wxString& name, const wxArgumentTypeArray& arguments, @@ -138,6 +139,8 @@ public: // getters { return m_args; } int GetLocation() const { return m_nLine; } + int GetAvailability() const + { return m_nAvailability; } bool IsConst() const { return m_bConst; } @@ -181,6 +184,8 @@ public: // setters { m_bDeprecated=c; } void SetLocation(int lineNumber) { m_nLine=lineNumber; } + void SetAvailability(int nAvail) + { m_nAvailability=nAvail; } public: // misc @@ -194,12 +199,22 @@ protected: wxType m_retType; wxString m_strName; wxArgumentTypeArray m_args; + + // misc attributes: bool m_bConst; bool m_bStatic; bool m_bVirtual; bool m_bPureVirtual; bool m_bDeprecated; + + // m_nLine can be -1 if no location infos are available int m_nLine; + + // this is a combination of wxPORT_* flags (see wxPortId) or wxPORT_UNKNOWN + // if this method should be available for all wxWidgets ports. + // NOTE: this is not used for comparing wxMethod objects + // (gccXML never gives this kind of info). + int m_nAvailability; }; WX_DECLARE_OBJARRAY(wxMethod, wxMethodArray); @@ -216,18 +231,18 @@ public: wxClass(const wxString& name, const wxString& headername) : m_strName(name), m_strHeader(headername) {} - void AddMethod(const wxMethod& func) - { m_methods.Add(func); } + +public: // setters void SetHeader(const wxString& header) { m_strHeader=header; } void SetName(const wxString& name) { m_strName=name; } - wxString GetName() const - { return m_strName; } - wxString GetHeader() const - { return m_strHeader; } - wxString GetNameWithoutTemplate() const; + void SetAvailability(int nAvail) + { m_nAvailability=nAvail; } + + +public: // getters bool IsOk() const { return !m_strName.IsEmpty() && !m_methods.IsEmpty(); } @@ -235,6 +250,12 @@ public: bool IsValidCtorForThisClass(const wxMethod& m) const; bool IsValidDtorForThisClass(const wxMethod& m) const; + wxString GetName() const + { return m_strName; } + wxString GetHeader() const + { return m_strHeader; } + wxString GetNameWithoutTemplate() const; + unsigned int GetMethodCount() const { return m_methods.GetCount(); } wxMethod& GetMethod(unsigned int n) const @@ -242,6 +263,14 @@ public: wxMethod& GetLastMethod() const { return m_methods.Last(); } + int GetAvailability() const + { return m_nAvailability; } + +public: // misc + + void AddMethod(const wxMethod& func) + { m_methods.Add(func); } + // returns a single result (the first, which is also the only // one if CheckConsistency() return true) const wxMethod* FindMethod(const wxMethod& m) const; @@ -260,6 +289,9 @@ protected: wxString m_strName; wxString m_strHeader; wxMethodArray m_methods; + + // see the wxMethod::m_nAvailability field for more info + int m_nAvailability; }; WX_DECLARE_OBJARRAY(wxClass, wxClassArray); @@ -333,12 +365,27 @@ typedef std::map wxTypeIdHashMap; class wxXmlGccInterface : public wxXmlInterface { public: - wxXmlGccInterface() {} + wxXmlGccInterface() + { + // FIXME: we should retrieve this from the XML file! + // here we suppose the XML was created for the currently-running port + m_portId = wxPlatformInfo::Get().GetPortId(); + } bool Parse(const wxString& filename); bool ParseMethod(const wxXmlNode *p, const wxTypeIdHashMap& types, wxMethod& m); + + wxPortId GetInterfacePort() const + { return m_portId; } + + wxString GetInterfacePortName() const + { return wxPlatformInfo::GetPortIdName(m_portId, false); } + +protected: + // the port for which the gcc XML was generated + wxPortId m_portId; }; -- 2.45.2