]> git.saurik.com Git - wxWidgets.git/commitdiff
add 'availability' infos to both wxMethod and wxClass: in this way ifacecheck does...
authorFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Thu, 27 Mar 2008 20:57:05 +0000 (20:57 +0000)
committerFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Thu, 27 Mar 2008 20:57:05 +0000 (20:57 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52863 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/doxygen/Doxyfile_inc
utils/ifacecheck/rungccxml.sh.in
utils/ifacecheck/src/ifacecheck.cpp
utils/ifacecheck/src/xmlparser.cpp
utils/ifacecheck/src/xmlparser.h

index 2fb298c0953a3955383d290b77eda308834af5e6..b487efb3083613b38942f3427109c4017b23df6e 100644 (file)
@@ -77,10 +77,12 @@ ALIASES += nativeimpl{3}="<div><span class='impl'>Implementations:</span>&nbsp;&
 ALIASES += nativeimpl{4}="<div><span class='impl'>Implementations:</span>&nbsp;&nbsp;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.</div>"
 
 # onlyfor infos:
-ALIASES += onlyfor{1}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1 port.</div>"
-ALIASES += onlyfor{2}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1, \ref page_port_\2 ports.</div>"
-ALIASES += onlyfor{3}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3 ports.</div>"
-ALIASES += onlyfor{4}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3, \ref page_port_\4 ports.</div>"
+# 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}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1 port.</div>       \xmlonly <onlyfor>\1</onlyfor> \endxmlonly"
+ALIASES += onlyfor{2}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1, \ref page_port_\2 ports.</div>       \xmlonly <onlyfor>\1,\2</onlyfor> \endxmlonly"
+ALIASES += onlyfor{3}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3 ports.</div>       \xmlonly <onlyfor>\1,\2,\3</onlyfor> \endxmlonly"
+ALIASES += onlyfor{4}="<div><span class='avail'>Availability:</span>&nbsp;&nbsp;only available for the \ref page_port_\1, \ref page_port_\2, \ref page_port_\3, \ref page_port_\4 ports.</div>       \xmlonly <onlyfor>\1,\2,\3,\4</onlyfor> \endxmlonly"
 
 # creates appearance section: this should be used for all main GUI controls
 ALIASES += appearance{1}="@htmlonly <div><span class='appearance'>Appearance:</span><br><table class='appearance'><tr><td><img src='wxmsw/\1' alt='wxMSW appearance' class='appearance'></td><td><img src='wxgtk/\1' alt='wxGTK appearance' class='appearance'></td><td><img src='wxmac/\1' alt='wxMac appearance' class='appearance'></td></tr><tr><td>wxMSW appearance</td><td>wxGTK appearance</td><td>wxMac appearance</td></tr></table></div> @endhtmlonly"
index fcd58240cc1367fc35e16b1dabb1a10a40b8dd33..c18eae5ae96a7fbe8e78cecd4298ad5a38108c6f 100755 (executable)
@@ -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
index d2c63869e60753605e433e0b9e90d647ed1ab060..a8ce9b2bc60799dd428b35ef6f83eed3d293a432 100644 (file)
@@ -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; i<interface.GetCount(); i++)
     {
+        // only compare the methods which are available for the port
+        // for which the gcc XML was produced
+        if (interface[i].GetAvailability() != wxPORT_UNKNOWN &&
+            (interface[i].GetAvailability() & m_gccInterface.GetInterfacePort()) == 0) {
+
+            if (g_verbose)
+                LogMessage("skipping class '%s' since it's not available for the %s port.",
+                           interface[i].GetName(), m_gccInterface.GetInterfacePortName());
+
+            continue;       // skip this method
+        }
+
         // shorten the name of the header so the log file is more readable
         // and also for calling IsToProcess() against it
         wxString header = wxFileName(interface[i].GetHeader()).GetFullName();
@@ -223,9 +235,9 @@ bool IfaceCheckApp::Compare()
         // for both class cname and cnameBase as in wxWidgets world, most often
         // class cname is platform-specific while the real public interface of
         // that class is part of the cnameBase class.
-        c = m_api.FindClass(cname);
+        c = m_gccInterface.FindClass(cname);
         if (c) api.Add(c);
-        c = m_api.FindClass(cname + "Base");
+        c = m_gccInterface.FindClass(cname + "Base");
         if (c) api.Add(c);
 
         if (api.GetCount()>0) {
@@ -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; j<api.GetCount(); j++)
         {
@@ -482,7 +506,7 @@ void IfaceCheckApp::FixMethod(const wxString& header, const wxMethod* iface, con
 
     // update the other method's locations for those methods which belong to the modified header
     // and are placed _below_ the modified method
-    wxClassPtrArray cToUpdate = m_interface.FindClassesDefinedIn(header);
+    wxClassPtrArray cToUpdate = m_doxyInterface.FindClassesDefinedIn(header);
     for (unsigned int i=0; i < cToUpdate.GetCount(); i++)
     {
         for (unsigned int j=0; j < cToUpdate[i]->GetMethodCount(); 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);
 }
 
index 69d5684f1d891984e0d7c381b21db608f8eb178f..43892d970d5627283f6384354aefeea716981915 100644 (file)
@@ -927,6 +927,121 @@ bool wxXmlGccInterface::ParseMethod(const wxXmlNode *p,
 }
 
 
+
+// ----------------------------------------------------------------------------
+// wxXmlDoxygenInterface global helpers
+// ----------------------------------------------------------------------------
+
+static wxString GetTextFromChildren(const wxXmlNode *n)
+{
+    wxString text;
+
+    // consider the tree
+    //
+    //  <a><b>this</b> is a <b>string</b></a>
+    //
+    // <a>
+    // |- <b>
+    // |   |- this
+    // |- is a
+    // |- <b>
+    //     |- 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 <onlyfor> 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 <onlyfor> 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
-    //
-    //  <a><b>this</b> is a <b>string</b></a>
-    //
-    // <a>
-    // |- <b>
-    // |   |- this
-    // |- is a
-    // |- <b>
-    //     |- 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 <detaileddescription>
             // a <xreftitle>Deprecated</xreftitle> tag.
             m.SetDeprecated(HasTextNodeContaining(child, "Deprecated"));
+
+            // identify <onlyfor> custom XML tags
+            m.SetAvailability(GetAvailabilityFor(child));
         }
 
         child = child->GetNext();
index 6e1de99a42fede5c8c12a40ff9f090bb2eae5c37..a593819279de0d851ab8300af78dfbdf6a76dd8b 100644 (file)
@@ -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<unsigned long, stlString> 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;
 };