Commit a06e1445 authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧
Browse files

Support scopes in CMake support

Only implemented for functions for the moment.

CCBUG: 238455
parent 1a09f323
......@@ -456,14 +456,19 @@ int CMakeProjectVisitor::visit(const AddLibraryAst *lib)
int CMakeProjectVisitor::visit(const SetAst *set)
{
//TODO: Must deal with ENV{something} case
QStringList values;
CacheValues::const_iterator itCache= m_cache->constFind(set->variableName());
if(set->storeInCache() && itCache!=m_cache->constEnd())
values = itCache->value.split(';');
else
values = set->values();
kDebug(9042) << "setting variable:" << set->variableName() /*<< "to" << values*/;
m_vars->insert(set->variableName(), values);
if(set->storeInCache()) {
QStringList values;
CacheValues::const_iterator itCache= m_cache->constFind(set->variableName());
if(itCache!=m_cache->constEnd())
values = itCache->value.split(';');
else
values = set->values();
m_vars->insertGlobal(set->variableName(), values);
} else
m_vars->insert(set->variableName(), set->values(), set->parentScope());
kDebug(9042) << "setting variable:" << set->variableName() << set->parentScope() /*<< "to" << values*/;
return 1;
}
......@@ -631,7 +636,7 @@ int CMakeProjectVisitor::visit(const FindPackageAst *pack)
foreach(const QString& possib, possibleConfigNames) {
path = findFile(possib, configPath);
if (!path.isEmpty()) {
m_vars->insert(pack->name()+"_DIR", QStringList(KUrl(path).directory()));
m_vars->insertGlobal(pack->name()+"_DIR", QStringList(KUrl(path).directory()));
isConfig=true;
break;
}
......@@ -678,7 +683,7 @@ int CMakeProjectVisitor::visit(const FindPackageAst *pack)
if(pack->noModule())
{
m_vars->insert(QString("%1_CONFIG").arg(pack->name()), QStringList(path));
m_vars->insertGlobal(QString("%1_CONFIG").arg(pack->name()), QStringList(path));
}
m_vars->remove("CMAKE_CURRENT_LIST_FILE");
m_vars->remove("CMAKE_CURRENT_LIST_DIR");
......@@ -692,7 +697,7 @@ int CMakeProjectVisitor::visit(const FindPackageAst *pack)
//FIXME: Put here the error.
kDebug(9032) << "error: Could not find" << pack->name() << "into" << modulePath;
}
m_vars->insert(QString("%1_DIR").arg(pack->name()), QStringList(QString("%1_DIR-NOTFOUND").arg(pack->name())));
m_vars->insertGlobal(QString("%1_DIR").arg(pack->name()), QStringList(QString("%1_DIR-NOTFOUND").arg(pack->name())));
}
kDebug(9042) << "Exit. Found:" << pack->name() << m_vars->value(pack->name()+"_FOUND");
......@@ -759,7 +764,6 @@ int CMakeProjectVisitor::visit(const FindProgramAst *fprog)
if(m_cache->contains(fprog->variableName()))
{
kDebug(9042) << "FindProgram: cache" << fprog->variableName() << m_cache->value(fprog->variableName()).value;
m_vars->insert(fprog->variableName(), m_cache->value(fprog->variableName()).value.split(';'));
return 1;
}
......@@ -782,9 +786,9 @@ int CMakeProjectVisitor::visit(const FindProgramAst *fprog)
}
if(!path.isEmpty())
m_vars->insert(fprog->variableName(), QStringList(path));
m_vars->insertGlobal(fprog->variableName(), QStringList(path));
else
m_vars->insert(fprog->variableName()+"-NOTFOUND", QStringList());
m_vars->insertGlobal(fprog->variableName()+"-NOTFOUND", QStringList());
kDebug(9042) << "FindProgram:" << fprog->variableName() << "=" << m_vars->value(fprog->variableName()) << modulePath;
return 1;
......@@ -814,7 +818,6 @@ int CMakeProjectVisitor::visit(const FindPathAst *fpath)
if(m_cache->contains(fpath->variableName()))
{
kDebug() << "FindPath: cache" << fpath->variableName();
m_vars->insert(fpath->variableName(), m_cache->value(fpath->variableName()).value.split(';'));
return 1;
}
......@@ -858,7 +861,7 @@ int CMakeProjectVisitor::visit(const FindPathAst *fpath)
if(!path.isEmpty())
{
m_vars->insert(fpath->variableName(), QStringList(path));
m_vars->insertGlobal(fpath->variableName(), QStringList(path));
}
else
{
......@@ -876,7 +879,6 @@ int CMakeProjectVisitor::visit(const FindLibraryAst *flib)
if(m_cache->contains(flib->variableName()))
{
kDebug(9042) << "FindLibrary: cache" << flib->variableName();
m_vars->insert(flib->variableName(), m_cache->value(flib->variableName()).value.split(';'));
return 1;
}
......@@ -929,7 +931,7 @@ int CMakeProjectVisitor::visit(const FindLibraryAst *flib)
if(!path.isEmpty())
{
m_vars->insert(flib->variableName(), QStringList(path));
m_vars->insertGlobal(flib->variableName(), QStringList(path));
}
else
kDebug(9032) << "error. Library" << flib->filenames() << "not found";
......@@ -945,7 +947,6 @@ int CMakeProjectVisitor::visit(const FindFileAst *ffile)
if(m_cache->contains(ffile->variableName()))
{
kDebug(9042) << "FindFile: cache" << ffile->variableName();
m_vars->insert(ffile->variableName(), m_cache->value(ffile->variableName()).value.split(';'));
return 1;
}
......@@ -988,7 +989,7 @@ int CMakeProjectVisitor::visit(const FindFileAst *ffile)
if(!path.isEmpty())
{
m_vars->insert(ffile->variableName(), QStringList(path));
m_vars->insertGlobal(ffile->variableName(), QStringList(path));
}
else
kDebug(9032) << "error. File" << ffile->filenames() << "not found";
......@@ -1172,11 +1173,16 @@ int CMakeProjectVisitor::visit(const MacroCallAst *call)
m_vars->insertMulti("ARGC", QStringList(QString::number(call->arguments().count())));
kDebug(9042) << "argn=" << m_vars->value("ARGN");
bool isfunc = code.isFunction;
if(isfunc)
m_vars->pushScope();
//Executing
int len = walk(code.code, 1);
kDebug(9042) << "visited!" << call->name() <<
m_vars->value("ARGV") << "_" << m_vars->value("ARGN") << "..." << len;
if(isfunc)
m_vars->popScope();
//Restoring
i=1;
foreach(const QString& name, code.knownArgs)
......@@ -2206,7 +2212,7 @@ int CMakeProjectVisitor::walk(const CMakeFileContent & fc, int line, bool isClea
createDefinitions(element);
m_vars->insert("CMAKE_CURRENT_LIST_LINE", QStringList(QString::number(it->line)));
m_vars->insertGlobal("CMAKE_CURRENT_LIST_LINE", QStringList(QString::number(it->line)));
int lines=element->accept(this);
line+=lines;
m_backtrace.top().line = line;
......
......@@ -137,6 +137,9 @@ class KDEVCMAKECOMMON_EXPORT CMakeProjectVisitor : CMakeAstVisitor
CMakeProperties properties() { return m_props; }
static void setMessageCallback(message_callback f) { s_msgcallback=f; }
QStringList variableValue(const QString& var) const;
protected:
struct IntPair
{
......@@ -178,7 +181,6 @@ class KDEVCMAKECOMMON_EXPORT CMakeProjectVisitor : CMakeAstVisitor
QStringList traverseGlob(const QString& startPath, const QString& expression,
bool recursive = false, bool followSymlinks = false);
QStringList variableValue(const QString& var) const;
CMakeProperties m_props;
QStringList m_modulePath;
......
......@@ -19,9 +19,27 @@
*/
#include "variablemap.h"
#include <QDebug>
QHash<QString, QStringList>::iterator VariableMap::insert(const QString & varName, const QStringList & value)
VariableMap::VariableMap()
{
m_scopes.push(QSet<QString>());
}
void VariableMap::insert(const QString& varName, const QStringList& value, bool parentScope)
{
QSet< QString >* current;
// qDebug() << "leeeeeeeeeeeeE" << varName << value << parentScope;
if(parentScope && m_scopes.size()>1) { //TODO: provide error?
current = &m_scopes[m_scopes.size()-2];
m_scopes.top().remove(varName);
} else
current = &m_scopes.top();
bool inscope=current->contains(varName);
if(!inscope)
current->insert(varName);
QStringList ret;
foreach(const QString& v, value)
{
......@@ -31,7 +49,20 @@ QHash<QString, QStringList>::iterator VariableMap::insert(const QString & varNam
ret += v.split(';');
}
return QHash<QString, QStringList>::insert(varName, ret);
if(inscope)
(*this)[varName]=ret;
else
QHash<QString, QStringList>::insertMulti(varName, ret);
// QHash<QString, QStringList>::insert(varName, ret);
// qDebug() << "++++++++" << varName << QHash<QString, QStringList>::value(varName)/* << *current*/;
}
QStringList VariableMap::value(const QString& varName) const
{
QStringList ret = QHash<QString, QStringList>::value(varName);
// qDebug() << "--------" << varName << ret;
return ret;
}
QHash<QString, QStringList>::iterator VariableMap::insertMulti(const QString & varName, const QStringList & value)
......@@ -47,3 +78,22 @@ QHash<QString, QStringList>::iterator VariableMap::insertMulti(const QString & v
return QHash<QString, QStringList>::insertMulti(varName, ret);
}
void VariableMap::insertGlobal(const QString& varName, const QStringList& value)
{
QHash<QString, QStringList>::insert(varName, value);
}
void VariableMap::pushScope()
{
m_scopes.push(QSet<QString>());
}
void VariableMap::popScope()
{
QSet<QString> t=m_scopes.pop();
foreach(const QString& var, t) {
// qDebug() << "removing........" << var/* << QHash<QString, QStringList>::value(var)*/;
remove(var);
}
}
......@@ -24,14 +24,20 @@
#include <QHash>
#include <QStringList>
#include "cmakeexport.h"
#include <QSet>
#include <QStack>
class KDEVCMAKECOMMON_EXPORT VariableMap : public QHash<QString, QStringList>
{
public:
VariableMap();
// bool contains(const QString& varName) const;
iterator insert(const QString& varName, const QStringList& value);
void insert(const QString& varName, const QStringList& value, bool parentScope = false);
///only for very special cases, usually should use insert. bypasses scopes
iterator insertMulti(const QString& varName, const QStringList& value);
// QStringList value(const QString& varName) const;
QStringList value(const QString& varName) const;
// QStringList take(const QString& varName);
// int remove(const QString& varName);
//
......@@ -43,6 +49,13 @@ class KDEVCMAKECOMMON_EXPORT VariableMap : public QHash<QString, QStringList>
#else
static QString regexEnvVar() { return "\\$ENV\\{[A-z0-9\\-._]+\\}"; }
#endif
void pushScope();
void popScope();
/** will create a variable without adding a scope on it */
void insertGlobal(const QString& key, const QStringList& value);
private:
QStack<QSet<QString> > m_scopes;
};
#endif
......@@ -435,6 +435,36 @@ void CMakeProjectVisitorTest::testRun_data()
QTest::newRow("unfinished foreach") <<
"foreach(VAR 1)\n"
<< cacheValues << results;
cacheValues.clear();
results.clear();
results << StringPair("X", "123");
QTest::newRow("var scope") <<
"function(HOLA)\n"
" set(X something_else)\n"
"endfunction(HOLA)\n"
"set(X 123)"
"HOLA()\n"
<< cacheValues << results;
cacheValues.clear();
results.clear();
results << StringPair("X", "something_else");
QTest::newRow("var scope parent") <<
"function(HOLA)\n"
" set(X something_else PARENT_SCOPE)\n"
"endfunction(HOLA)\n"
"set(X 123)\n"
"HOLA()\n"
<< cacheValues << results;
cacheValues.clear();
results.clear();
results << StringPair("X", "something_else");
QTest::newRow("var scope cache") <<
"function(HOLA)\n"
" set(X something_else CACHE STRING lala)\n"
"endfunction(HOLA)\n"
"set(X 123)\n"
"HOLA()\n"
<< cacheValues << results;
}
void CMakeProjectVisitorTest::testRun()
......@@ -477,7 +507,7 @@ void CMakeProjectVisitorTest::testRun()
CMakeFunctionArgument arg;
arg.value=vp.first;
QCOMPARE(vm.value(vp.first).join(QString(";")), vp.second);
QCOMPARE(v.variableValue(vp.first).join(QString(";")), vp.second);
}
{
KDevelop::DUChainWriteLocker lock(DUChain::lock());
......@@ -490,14 +520,16 @@ void CMakeProjectVisitorTest::testFinder_data()
QTest::addColumn<QString>("module");
QTest::addColumn<QString>("args");
QTest::newRow("ZLIB") << "ZLIB" << QString();
QTest::newRow("PNG") << "PNG" << QString();
QTest::newRow("Qt4") << "Qt4" << QString();
QTest::newRow("Qt4comp") << "Qt4" << QString("COMPONENTS QtCore QtGui");
QTest::newRow("KDE4") << "KDE4" << QString();
QTest::newRow("Automoc4") << "Automoc4" << QString();
// QTest::newRow("Boost") << "Boost" << QString("1.39");
// QTest::newRow("Eigen2") << "Eigen2";
// QTest::newRow("Exiv2") << "Exiv2";
QTest::newRow("QtGStreamer") << "QtGStreamer" << QString(); //commented because it might not be installed, but works
QTest::newRow("Boost") << "Boost" << QString("1.39");
// QTest::newRow("Eigen2") << "Eigen2" << QString();
// QTest::newRow("Exiv2") << "Exiv2" << QString();
// QTest::newRow("QtGStreamer") << "QtGStreamer" << QString(); //commented because it might not be installed
}
void CMakeProjectVisitorTest::testFinder_init()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment