tools/porting/src/portingrules.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the qt3to4 porting application of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "portingrules.h"
       
    43 #include "logger.h"
       
    44 #include "qtsimplexml.h"
       
    45 #include <QFile>
       
    46 #include <QFileInfo>
       
    47 #include <QDir>
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 
       
    51 PortingRules *PortingRules::theInstance  = 0;
       
    52 
       
    53 void PortingRules::createInstance(QString xmlFilePath)
       
    54 {
       
    55     deleteInstance();
       
    56     theInstance  = new PortingRules(xmlFilePath);
       
    57 }
       
    58 
       
    59 PortingRules *PortingRules::instance()
       
    60 {
       
    61     if(theInstance) {
       
    62         return theInstance;
       
    63     } else {
       
    64         qWarning("Error: must create a PortingRules instance with createInstance() before calling instance()\n");
       
    65         return 0;
       
    66     }
       
    67 }
       
    68 
       
    69 void PortingRules::deleteInstance()
       
    70 {
       
    71     if(theInstance) {
       
    72         delete theInstance;
       
    73         theInstance = 0;
       
    74     }
       
    75 }
       
    76 
       
    77 PortingRules::PortingRules(QString xmlFilePath)
       
    78 {
       
    79     parseXml(xmlFilePath);
       
    80 }
       
    81 
       
    82 QList<TokenReplacement*> PortingRules::getTokenReplacementRules()
       
    83 {
       
    84     if(tokenRules.isEmpty())
       
    85          addLogWarning(QLatin1String("Warning: token rules list is empty"));
       
    86     return tokenRules;
       
    87 }
       
    88 
       
    89 QStringList PortingRules::getHeaderList(QtVersion qtVersion)
       
    90 {
       
    91     if(qt3Headers.isEmpty() || qt4Headers.isEmpty())
       
    92          addLogWarning(QLatin1String("Warning: headers list is empty"));
       
    93 
       
    94     if (qtVersion==Qt3)
       
    95         return qt3Headers;
       
    96     else //Qt4
       
    97         return qt4Headers;
       
    98 }
       
    99 
       
   100 QHash<QByteArray, QByteArray> PortingRules::getNeededHeaders()
       
   101 {
       
   102     if(neededHeaders.isEmpty())
       
   103          addLogWarning(QLatin1String("Warning: needed headers list is empty"));
       
   104     return neededHeaders;
       
   105 }
       
   106 
       
   107 QStringList PortingRules::getInheritsQt()
       
   108 {
       
   109     if(tokenRules.isEmpty())
       
   110         addLogWarning(QLatin1String("Warning: inheritsQtClass list is empty"));
       
   111     return inheritsQtClass;
       
   112 }
       
   113 
       
   114 QHash<QByteArray, QByteArray> PortingRules::getClassLibraryList()
       
   115 {
       
   116     if(classLibraryList.isEmpty())
       
   117         addLogWarning(QLatin1String("Warning: classLibraryList list is empty"));
       
   118     return classLibraryList;
       
   119 }
       
   120 
       
   121 QHash<QByteArray, QByteArray> PortingRules::getHeaderReplacements()
       
   122 {
       
   123     return headerReplacements;
       
   124 }
       
   125 
       
   126 /*
       
   127     Loads rule xml file given by fileName, and sets up data structures.
       
   128     The rules can generally be divided into to types, replacement rules and
       
   129     info rules.
       
   130 
       
   131     Replacement rules has the form Qt3Symobl -> Qt4Symbol
       
   132     Info rules includes the NeedHeader, Qt3Header, Qt4Header, InhertitsQt
       
   133     rule types.
       
   134 */
       
   135 void PortingRules::parseXml(QString fileName)
       
   136 {
       
   137     QtSimpleXml *xmlPointer = loadXml(fileName);
       
   138     QtSimpleXml &xml = *xmlPointer;
       
   139 
       
   140     int ruleCount = xml[QLatin1String("Rules")].numChildren();
       
   141     ++ruleCount;
       
   142 
       
   143     for(int rule=0; rule<ruleCount; ++rule) {
       
   144         QtSimpleXml &currentRule = xml[QLatin1String("Rules")][rule];
       
   145         QString ruleType = currentRule.attribute(QLatin1String("Type"));
       
   146 
       
   147         if(isReplacementRule(ruleType)) {
       
   148             QString qt3Symbol = currentRule[QLatin1String("Qt3")].text();
       
   149             QString qt4Symbol = currentRule[QLatin1String("Qt4")].text();
       
   150 
       
   151             QString disable = currentRule.attribute(QLatin1String("Disable"));
       
   152             if(disable == QLatin1String("True") || disable == QLatin1String("true")) {
       
   153                 disableRule(currentRule);
       
   154                 continue;
       
   155             }
       
   156 
       
   157             if (isRuleDisabled(currentRule))
       
   158                 continue;
       
   159 
       
   160             if(ruleType == QLatin1String("RenamedHeader")) {
       
   161               headerReplacements.insert(qt3Symbol.toLatin1(), qt4Symbol.toLatin1());
       
   162             } else if(ruleType == QLatin1String("RenamedClass") || ruleType == QLatin1String("RenamedToken") ) {
       
   163                 tokenRules.append(new ClassNameReplacement(
       
   164                         qt3Symbol.toLatin1(), qt4Symbol.toLatin1()));
       
   165             } else if(ruleType == QLatin1String("RenamedEnumvalue") || ruleType == QLatin1String("RenamedType") ||
       
   166                     ruleType == QLatin1String("RenamedQtSymbol") ) {
       
   167                 checkScopeAddRule(currentRule);
       
   168             }
       
   169         } else if(ruleType == QLatin1String("NeedHeader")) {
       
   170             const QByteArray className = currentRule[QLatin1String("Class")].text().toLatin1();
       
   171             const QByteArray headerName = currentRule[QLatin1String("Header")].text().toLatin1();
       
   172             neededHeaders.insert(className, headerName);
       
   173         }
       
   174         else if(ruleType == QLatin1String("qt3Header")) {
       
   175             qt3Headers += currentRule.text();
       
   176         }
       
   177         else if(ruleType == QLatin1String("qt4Header")) {
       
   178             qt4Headers += currentRule.text();
       
   179         }
       
   180         else if(ruleType == QLatin1String("InheritsQt")) {
       
   181             inheritsQtClass += currentRule.text();
       
   182         }
       
   183         else if(ruleType == QLatin1String("Qt4Class")) {
       
   184             // Get library name, make it lowercase and chop of the "Qt" prefix.
       
   185             const QByteArray libraryName = currentRule[QLatin1String("Library")].text().toLatin1().toLower().mid(2);
       
   186             classLibraryList.insert(currentRule[QLatin1String("Name")].text().toLatin1(), libraryName);
       
   187         }
       
   188     }
       
   189 
       
   190     QString includeFile = xml[QLatin1String("Rules")][QLatin1String("Include")].text();
       
   191 
       
   192     if(!includeFile.isNull()) {
       
   193         QString resolvedIncludeFile = resolveFileName(fileName, includeFile);
       
   194         if (!resolvedIncludeFile.isEmpty())
       
   195             parseXml(resolvedIncludeFile);
       
   196     }
       
   197 
       
   198     delete xmlPointer;
       
   199 }
       
   200 
       
   201 /*
       
   202     Check if the rule in currentRule describes a qualified name
       
   203     (like QButton::ToggleState). If so, create a scoped ScopedTokenReplacement,
       
   204     else create a GenericTokenReplacement
       
   205 */
       
   206 void PortingRules::checkScopeAddRule(/*const */QtSimpleXml &currentRule)
       
   207 {
       
   208     QByteArray oldToken = currentRule[QLatin1String("Qt3")].text().toLatin1();
       
   209     QByteArray newToken = currentRule[QLatin1String("Qt4")].text().toLatin1();
       
   210 
       
   211     if (oldToken.contains(QByteArray("::")))
       
   212         tokenRules.append(new ScopedTokenReplacement(oldToken, newToken));
       
   213     else
       
   214         tokenRules.append(new GenericTokenReplacement(oldToken, newToken));
       
   215 }
       
   216 
       
   217 /*
       
   218     Loads the xml-file given by fileName into a new'ed QtSimpleXml, which is
       
   219     returned by pointer.
       
   220 */
       
   221 QtSimpleXml *PortingRules::loadXml(const QString fileName) const
       
   222 {
       
   223     QFile f(fileName);
       
   224     if(!f.open(QIODevice::ReadOnly)) {
       
   225         qFatal("Could not find rule file %s", fileName.toLatin1().constData());
       
   226     }
       
   227     QtSimpleXml *xml = new QtSimpleXml();
       
   228     if(!xml->setContent(&f))
       
   229         addLogError(QLatin1String("Xml parsing failed: ") + xml->errorString());
       
   230 
       
   231     return xml;
       
   232 }
       
   233 
       
   234 /*
       
   235     Resolves includeFilePath against currentFilePath. If currentFilePath
       
   236     contains foo/bar.xml, and includeFilePath contains bar2.xml, the returned
       
   237     result will be foo/bar2.xml. If includeFilePath is absolute, it is returned
       
   238     unmodified.
       
   239 */
       
   240 QString PortingRules::resolveFileName(const QString currentFilePath,
       
   241                                       const QString includeFilePath) const
       
   242 {
       
   243     if(QFileInfo(includeFilePath).isAbsolute())
       
   244         return includeFilePath;
       
   245     QString relativeDirectory = QFileInfo(currentFilePath).dir().dirName();
       
   246     QString testFileName = relativeDirectory + QLatin1String("/") + includeFilePath;
       
   247     if (QFile::exists(testFileName))
       
   248         return testFileName;
       
   249 
       
   250     return QString();
       
   251 }
       
   252 /*
       
   253     Checks if a rule is a replacement rule.
       
   254 */
       
   255 bool PortingRules::isReplacementRule(const QString ruleType) const
       
   256 {
       
   257     return (ruleType == QLatin1String("RenamedHeader") || ruleType == QLatin1String("RenamedClass") ||
       
   258             ruleType == QLatin1String("RenamedToken") || ruleType == QLatin1String("RenamedEnumvalue") ||
       
   259             ruleType == QLatin1String("RenamedType") || ruleType == QLatin1String("RenamedQtSymbol") );
       
   260 }
       
   261 
       
   262 /*
       
   263     Disables a replacement rule given by the replacementRule parameter
       
   264 */
       
   265 void PortingRules::disableRule(QtSimpleXml &replacementRule)
       
   266 {
       
   267     RuleDescription ruleDescription(replacementRule);
       
   268     disabledRules.append(ruleDescription);
       
   269 }
       
   270 
       
   271 /*
       
   272     Checks if a replacement rule is disabled or not
       
   273 */
       
   274 bool PortingRules::isRuleDisabled(QtSimpleXml &replacementRule) const
       
   275 {
       
   276     RuleDescription ruleDescription(replacementRule);
       
   277     return disabledRules.contains(ruleDescription);
       
   278 }
       
   279 
       
   280 /*
       
   281     Adds a warning to the global logger.
       
   282 */
       
   283 void PortingRules::addLogWarning(const QString text) const
       
   284 {
       
   285     Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Warning"), QLatin1String("Porting"), text));
       
   286 }
       
   287 
       
   288 /*
       
   289     Adds an error to the global logger.
       
   290 */
       
   291 void PortingRules::addLogError(const QString text) const
       
   292 {
       
   293     Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), text));
       
   294 }
       
   295 
       
   296 QT_END_NAMESPACE