Merge remote-tracking branch 'origin/2.6'

Conflicts:
	src/plugins/cpptools/cppcompletion_test.cpp
	src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
	src/plugins/qmlprojectmanager/qmlprojectapplicationwizard.cpp
	src/plugins/qtsupport/baseqtversion.cpp
	tests/auto/cplusplus/findusages/tst_findusages.cpp

Change-Id: Idd2abc09753a71a6c252bfa9914274459b2c7e63
This commit is contained in:
Eike Ziller
2012-11-26 10:52:28 +01:00
64 changed files with 860 additions and 324 deletions

12
.gitignore vendored
View File

@@ -111,8 +111,10 @@ bin/qml2puppet.exe
bin/qtpromaker
bin/qtpromaker.exe
share/doc/qtcreator/*.qch
src/tools/gen-cpp-ast/generate-ast
src/tools/mkvisitor/cplusplus0
src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor
src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.exe
src/tools/cplusplus-update-frontend/cplusplus-update-frontend
src/tools/cplusplus-update-frontend/cplusplus-update-frontend.exe
src/tools/qml/qmldump/qmldump
src/tools/examplesscanner/examplesscanner
src/tools/valgrindfake/valgrind-fake
@@ -120,13 +122,15 @@ bin/*.exe
# Tests
#------
tests/manual/cplusplus-frontend/cplusplus0
tests/manual/cplusplus-dump/cplusplus0
tests/manual/cplusplus-frontend/cplusplus-frontend
tests/manual/cplusplus-frontend/cplusplus-frontend.exe
tests/manual/qml-ast2dot/qml-ast2dot
tests/manual/debugger/simple/libsimple_test_plugin.*dylib
tests/manual/debugger/simple/simple_test_app
tests/manual/plain-cplusplus/plain-c++
tests/manual/preprocessor/pp
tests/tools/cplusplus-ast2png/cplusplus-ast2png
tests/tools/cplusplus-ast2png/cplusplus-ast2png.exe
tests/auto/cplusplus/codegen/tst_codegen
tests/auto/cplusplus/ast/tst_ast
tests/auto/cplusplus/codeformatter/tst_codeformatter

View File

@@ -31,7 +31,7 @@
\title Using External Tools
You can use external tools directly from \QC. Qt Linguist,
QML Viewer, the
QML preview tools, the
default text editor for your system, and the \c sort tool are preconfigured
for use. You can change their default configurations and configure new
tools.
@@ -59,14 +59,14 @@
\l{http://qt-project.org/doc/qt-4.8/linguist-manual.html}
{Qt Linguist Manual}.
\section1 Using QML Viewer
\section1 Previewing QML Files
You can preview the current QML document in the QML Viewer. The QML Viewer
invokes the QML runtime to load QML documents and also includes additional
features useful for the development of QML-based applications.
You can preview the current QML document in the QML Viewer (Qt Quick 1) or
QML Scene (Qt Quick 2). The preview tools enable you to load QML documents
for viewing and testing while you are developing an application.
To preview the currently active QML file, select \gui {Tools > External >
Qt Quick > Preview (qmlviewer)}.
To preview the currently active QML file, select \gui Tools > \gui External
> \gui {Qt Quick} > \gui {Preview (qmlviewer)} or \gui {Preview (qmlscene)}.
\section1 Using External Text Editors

View File

@@ -71,7 +71,8 @@
\o \l{Using External Tools}
You can use external tools directly from \QC. Qt Linguist,
QML Viewer, the default text editor for your system, and the \c sort
QML preview tools (QML Viewer and QML Scene), the default text
editor for your system, and the \c sort
tool are preconfigured for use. You can change their default
configurations and configure new tools.

View File

@@ -141,8 +141,9 @@
\o Qt Quick UI
Use a single QML file that contains the main view. You can run
Qt Quick UI projects in the QML Viewer and you need not build
Use a single QML file that contains the main view. You can
review Qt Quick UI projects in a \l{Previewing QML Files}
{preview tool} and you need not build
them. You do not need to have the development environment
installed on your computer to create and run this type of
projects
@@ -273,7 +274,11 @@
\o Qt resource files, which allow you to store binary files in the
application executable
\o QML files, which specify elements in Qt Quick projects
\o QML files, which specify elements in Qt Quick projects.
\gui {Qt Quick 1} creates a QML file that imports Qt Quick 1.1 and
\gui {Qt Quick 2} creates a QML file that imports Qt Quick 2.0.
Select \gui {Qt Quick 1} to add files to a Qt Quick 1 application
and \gui {Qt Quick 2} to add files to a Qt Quick 2 application.
\o JavaScript files that you can use to write the application logic in
Qt Quick projects

View File

@@ -59,7 +59,8 @@
develop for platforms that run Qt 5.
\o \gui {Qt Quick UI} creates a Qt Quick UI project with a single QML
file that contains the main view. You can review Qt Quick UI
projects in the QML Viewer and you need not build them. You do not
projects in a \l{Previewing QML Files}{preview tool} and you need
not build them. You do not
need to have the development environment installed on your
computer to create and run this type of project.

View File

@@ -127,10 +127,13 @@ macx {
IDE_BIN_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/MacOS
copydata = 1
isEmpty(TIGER_COMPAT_MODE):TIGER_COMPAT_MODE=$$(QTC_TIGER_COMPAT)
!isEqual(QT_MAJOR_VERSION, 5) {
# Qt5 doesn't support 10.5, and will set the minimum version correctly to 10.6 or 10.7.
isEmpty(TIGER_COMPAT_MODE) {
QMAKE_CXXFLAGS *= -mmacosx-version-min=10.5
QMAKE_LFLAGS *= -mmacosx-version-min=10.5
}
}
} else {
contains(TEMPLATE, vc.*):vcproj = 1
IDE_APP_TARGET = qtcreator

View File

@@ -7831,7 +7831,7 @@ konnte dem Projekt &apos;%2&apos; nicht hinzugefügt werden.</translation>
</message>
<message>
<source>&amp;Debug</source>
<translation>&amp;Debuggen</translation>
<translation>Deb&amp;uggen</translation>
</message>
<message>
<source>&amp;Start Debugging</source>

View File

@@ -29,7 +29,7 @@
/*
All firstToken/lastToken methods below which have a doxygen comment with
\generated in it, will be re-generated when the tool "generate-ast" is run.
\generated in it, will be re-generated when the tool "cplusplus-update-frontend" is run.
For methods which are hand-coded, or which should not be changed, make sure that
the comment is gone.

View File

@@ -181,7 +181,11 @@ bool MakeStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
pp->setEnvironment(bc->environment());
Utils::Environment env = bc->environment();
// Force output to english for the parsers. Do this here and not in the toolchain's
// addToEnvironment() to not screw up the users run environment.
env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
pp->setEnvironment(env);
pp->setWorkingDirectory(bc->buildDirectory());
pp->setCommand(tc ? tc->makeCommand(bc->environment()) : QLatin1String("make"));
pp->setArguments(arguments);

View File

@@ -188,14 +188,13 @@ bool MakeStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
if (m_useNinja) {
Utils::Environment env = bc->environment();
if (!env.value(QLatin1String("NINJA_STATUS")).startsWith(m_ninjaProgressString))
// Force output to english for the parsers. Do this here and not in the toolchain's
// addToEnvironment() to not screw up the users run environment.
env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
if (m_useNinja && !env.value(QLatin1String("NINJA_STATUS")).startsWith(m_ninjaProgressString))
env.set(QLatin1String("NINJA_STATUS"), m_ninjaProgressString + QLatin1String("%o/sec] "));
pp->setEnvironment(env);
} else {
pp->setEnvironment(bc->environment());
}
pp->setWorkingDirectory(bc->buildDirectory());
pp->setCommand(makeCommand(tc, bc->environment()));
pp->setArguments(arguments);

View File

@@ -1051,5 +1051,4 @@ void CppToolsPlugin::test_completion_enclosing_template_class_data()
completions.append(QLatin1String("int_nested"));
QTest::newRow("case: nested template class with enclosing template class")
<< code << completions;
}

View File

@@ -136,7 +136,7 @@ bool Debugger::Internal::interruptProcess(int pID, int engineType, QString *erro
*errorMessage = QLatin1String("DebugBreakProcess failed: ") + Utils::winErrorMessage(GetLastError());
} else {
const QString executable = QCoreApplication::applicationDirPath() + QLatin1String("/win64interrupt.exe");
switch (QProcess::execute(executable + QLatin1Char(' ') + QString::number(pID))) {
switch (QProcess::execute(executable, QStringList(QString::number(pID)))) {
case -2:
*errorMessage = QString::fromLatin1("Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c for more information.").
arg(QDir::toNativeSeparators(executable));

View File

@@ -251,7 +251,8 @@ void QmlInspectorAdapter::engineClientStatusChanged(QmlDebug::ClientStatus statu
BaseEngineDebugClient *client
= qobject_cast<BaseEngineDebugClient*>(sender());
if (status == QmlDebug::Enabled) {
if (status == QmlDebug::Enabled && !m_engineClientConnected) {
// We accept the first client that is enabled and reject the others.
QTC_ASSERT(client, return);
setActiveEngineClient(client);
} else if (m_engineClientConnected && client == m_engineClient) {

View File

@@ -62,6 +62,7 @@ QmlInspectorAgent::QmlInspectorAgent(DebuggerEngine *engine, QObject *parent)
, m_objectToSelect(-1)
, m_newObjectsCreated(false)
{
m_debugIdToIname.insert(-1, QByteArray("inspect"));
connect(debuggerCore()->action(ShowQmlObjectTree),
SIGNAL(valueChanged(QVariant)), SLOT(updateStatus()));
m_delayQueryTimer.setSingleShot(true);
@@ -452,17 +453,17 @@ void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value,
}
if (m_objectTreeQueryIds.contains(queryId)) {
m_objectTreeQueryIds.removeOne(queryId);
if (value.type() == QVariant::List) {
QVariantList objList = value.toList();
foreach (QVariant var, objList) {
// TODO: check which among the list is the actual
// object that needs to be selected.
insertObjectInTree(qvariant_cast<ObjectReference>(var));
verifyAndInsertObjectInTree(qvariant_cast<ObjectReference>(var));
}
} else {
insertObjectInTree(qvariant_cast<ObjectReference>(value));
verifyAndInsertObjectInTree(qvariant_cast<ObjectReference>(value));
}
m_objectTreeQueryIds.removeOne(queryId);
} else if (queryId == m_engineQueryId) {
m_engineQueryId = 0;
QList<EngineReference> engines = qvariant_cast<QList<EngineReference> >(value);
@@ -608,13 +609,13 @@ void QmlInspectorAgent::updateObjectTree(const ContextReference &context)
return;
foreach (const ObjectReference & obj, context.objects())
insertObjectInTree(obj);
verifyAndInsertObjectInTree(obj);
foreach (const ContextReference &child, context.contexts())
updateObjectTree(child);
}
void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object)
void QmlInspectorAgent::verifyAndInsertObjectInTree(const ObjectReference &object)
{
if (debug)
qDebug() << __FUNCTION__ << '(' << object << ')';
@@ -622,17 +623,56 @@ void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object)
if (!object.isValid())
return;
// Find out the correct position in the tree
// Objects are inserted to the tree if they satisfy one of the two conditions.
// Condition 1: Object is a root object i.e. parentId == -1.
// Condition 2: Object has an expanded parent i.e. siblings are known.
// If the two conditions are not met then we push the object to a stack and recursively
// fetch parents till we find a previously expanded parent.
WatchHandler *handler = m_debuggerEngine->watchHandler();
const int parentId = object.parentId();
const int objectDebugId = object.debugId();
if (m_debugIdToIname.contains(parentId)) {
QByteArray parentIname = m_debugIdToIname.value(parentId);
if (parentId != -1 && !handler->isExpandedIName(parentIname)) {
m_objectStack.push(object);
handler->model()->fetchMore(handler->watchDataIndex(parentIname));
return; // recursive
}
insertObjectInTree(object);
} else {
m_objectStack.push(object);
fetchObject(parentId);
return; // recursive
}
if (!m_objectStack.isEmpty()) {
const ObjectReference &top = m_objectStack.top();
// We want to expand only a particular branch and not the whole tree. Hence, we do not
// expand siblings.
if (object.children().contains(top)) {
QByteArray objectIname = m_debugIdToIname.value(objectDebugId);
if (!handler->isExpandedIName(objectIname)) {
handler->model()->fetchMore(handler->watchDataIndex(objectIname));
} else {
verifyAndInsertObjectInTree(m_objectStack.pop());
return; // recursive
}
}
}
}
void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object)
{
if (debug)
qDebug() << __FUNCTION__ << '(' << object << ')';
const int objectDebugId = object.debugId();
const int parentId = parentIdForIname(m_debugIdToIname.value(objectDebugId));
QElapsedTimer timeElapsed;
// sync tree with watchhandler
QList<WatchData> watchData;
int objectDebugId = object.debugId();
// When root items are inserted in the object tree, m_objectTreeQueryIds = 0
if (!m_debugIdToIname.contains(objectDebugId) && m_objectTreeQueryIds.count())
return;
int parentId = parentIdForIname(m_debugIdToIname.value(objectDebugId));
if (debug)
timeElapsed.start();
watchData.append(buildWatchData(object, m_debugIdToIname.value(parentId), true));
@@ -829,6 +869,7 @@ void QmlInspectorAgent::clearObjectTree()
m_debugIdHash.clear();
m_debugIdHash.reserve(old_count + 1);
m_debugIdToIname.clear();
m_debugIdToIname.insert(-1, QByteArray("inspect"));
m_objectStack.clear();
// reset only for qt > 4.8.3.
if (m_engineClient->objectName() != QLatin1String(QDECLARATIVE_ENGINE))

View File

@@ -110,7 +110,7 @@ private slots:
private:
void updateObjectTree(const QmlDebug::ContextReference &context);
void verifyAndInsertObjectInTree(const QmlDebug::ObjectReference &object);
void insertObjectInTree(const QmlDebug::ObjectReference &result);
void buildDebugIdHashRecursive(const QmlDebug::ObjectReference &ref);

View File

@@ -1809,6 +1809,11 @@ const WatchData *WatchHandler::watchData(const QModelIndex &idx) const
return m_model->watchItem(idx);
}
const QModelIndex WatchHandler::watchDataIndex(const QByteArray &iname) const
{
return m_model->watchIndex(m_model->findItem(iname));
}
const WatchData *WatchHandler::findData(const QByteArray &iname) const
{
return m_model->findItem(iname);

View File

@@ -85,6 +85,7 @@ public:
void showEditValue(const WatchData &data);
const WatchData *watchData(const QModelIndex &) const;
const QModelIndex watchDataIndex(const QByteArray &iname) const;
const WatchData *findData(const QByteArray &iname) const;
const WatchData *findCppLocalVariable(const QString &name) const;
QString displayForAutoTest(const QByteArray &iname) const;

View File

@@ -114,7 +114,11 @@ bool GenericMakeStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
pp->setWorkingDirectory(bc->buildDirectory());
pp->setEnvironment(bc->environment());
Utils::Environment env = bc->environment();
// Force output to english for the parsers. Do this here and not in the toolchain's
// addToEnvironment() to not screw up the users run environment.
env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
pp->setEnvironment(env);
pp->setCommand(makeCommand(bc->environment()));
pp->setArguments(allArguments());

View File

@@ -402,7 +402,7 @@ void BuildManager::nextBuildQueue()
addToOutputWindow(tr("Error while building/deploying project %1 (kit: %2)").arg(projectName, targetName), BuildStep::ErrorOutput);
addToOutputWindow(tr("When executing step '%1'").arg(d->m_currentBuildStep->displayName()), BuildStep::ErrorOutput);
// NBS TODO fix in qtconcurrent
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, tr("Error while building/deploying project %1 (target: %2)").arg(projectName, targetName));
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, tr("Error while building/deploying project %1 (kit: %2)").arg(projectName, targetName));
}
if (result)
@@ -502,7 +502,7 @@ bool BuildManager::buildQueueAppend(QList<BuildStep *> steps, QStringList names)
// print something for the user
const QString projectName = bs->project()->displayName();
const QString targetName = bs->target()->displayName();
addToOutputWindow(tr("Error while building/deploying project %1 (target: %2)").arg(projectName, targetName), BuildStep::ErrorOutput);
addToOutputWindow(tr("Error while building/deploying project %1 (kit: %2)").arg(projectName, targetName), BuildStep::ErrorOutput);
addToOutputWindow(tr("When executing step '%1'").arg(bs->displayName()), BuildStep::ErrorOutput);
// disconnect the buildsteps again

View File

@@ -44,6 +44,7 @@ class IOutputParser;
namespace Internal {
class KitManagerPrivate;
class KitModel;
class KitPrivate;
} // namespace Internal
@@ -110,6 +111,7 @@ private:
Internal::KitPrivate *d;
friend class KitManager;
friend class Internal::KitModel; // needed for setAutoDetected() when cloning kits
};
class KitGuard

View File

@@ -89,7 +89,6 @@ QList<Task> SysRootKitInformation::validate(const Kit *k) const
KitConfigWidget *SysRootKitInformation::createConfigWidget(Kit *k) const
{
Q_ASSERT(k);
return new Internal::SysRootInformationConfigWidget(k);
}
@@ -184,7 +183,6 @@ void ToolChainKitInformation::fix(Kit *k)
KitConfigWidget *ToolChainKitInformation::createConfigWidget(Kit *k) const
{
Q_ASSERT(k);
return new Internal::ToolChainInformationConfigWidget(k);
}

View File

@@ -115,7 +115,7 @@ KitManager::KitManager(QObject *parent) :
QObject(parent),
d(new Internal::KitManagerPrivate())
{
Q_ASSERT(!m_instance);
QTC_CHECK(!m_instance);
m_instance = this;
connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
@@ -257,7 +257,7 @@ void KitManager::registerKitInformation(KitInformation *ki)
void KitManager::deregisterKitInformation(KitInformation *ki)
{
Q_ASSERT(d->m_informationList.contains(ki));
QTC_CHECK(d->m_informationList.contains(ki));
d->m_informationList.removeAll(ki);
delete ki;
}

View File

@@ -93,6 +93,9 @@ KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
KitManagerConfigWidget::~KitManagerConfigWidget()
{
qDeleteAll(m_widgets);
m_widgets.clear();
delete m_modifiedKit;
// Make sure our workingCopy did not get registered somehow:
foreach (const Kit *k, KitManager::instance()->kits())
@@ -106,17 +109,18 @@ QString KitManagerConfigWidget::displayName() const
void KitManagerConfigWidget::apply()
{
bool mustSetDefault = m_isDefaultKit;
KitManager *km = KitManager::instance();
bool mustRegister = false;
if (!m_kit) {
mustRegister = true;
m_kit = new Kit;
}
m_kit->copyFrom(m_modifiedKit);
m_kit->copyFrom(m_modifiedKit);//m_isDefaultKit is reset in discard() here.
if (mustRegister)
km->registerKit(m_kit);
if (m_isDefaultKit)
if (mustSetDefault)
km->setDefaultKit(m_kit);
emit dirty();
}
@@ -190,7 +194,7 @@ bool KitManagerConfigWidget::configures(Kit *k) const
void KitManagerConfigWidget::setIsDefaultKit(bool d)
{
if (m_isDefaultKit != d)
if (m_isDefaultKit == d)
return;
m_isDefaultKit = d;
emit dirty();

View File

@@ -76,7 +76,6 @@ public:
// so operate on a temporary list
QList<KitNode *> tmp = childNodes;
qDeleteAll(tmp);
Q_ASSERT(childNodes.isEmpty());
}
KitNode *parent;
@@ -93,8 +92,6 @@ KitModel::KitModel(QBoxLayout *parentLayout, QObject *parent) :
m_parentLayout(parentLayout),
m_defaultNode(0)
{
Q_ASSERT(m_parentLayout);
connect(KitManager::instance(), SIGNAL(kitAdded(ProjectExplorer::Kit*)),
this, SLOT(addKit(ProjectExplorer::Kit*)));
connect(KitManager::instance(), SIGNAL(kitRemoved(ProjectExplorer::Kit*)),
@@ -196,7 +193,6 @@ Qt::ItemFlags KitModel::flags(const QModelIndex &index) const
return 0;
KitNode *node = static_cast<KitNode *>(index.internalPointer());
Q_ASSERT(node);
if (!node->widget)
return Qt::ItemIsEnabled;
@@ -216,7 +212,6 @@ Kit *KitModel::kit(const QModelIndex &index)
if (!index.isValid())
return 0;
KitNode *node = static_cast<KitNode *>(index.internalPointer());
Q_ASSERT(node);
return node->widget->workingCopy();
}
@@ -231,7 +226,6 @@ void KitModel::setDefaultKit(const QModelIndex &index)
if (!index.isValid())
return;
KitNode *node = static_cast<KitNode *>(index.internalPointer());
Q_ASSERT(node);
if (node->widget)
setDefaultNode(node);
}
@@ -246,7 +240,6 @@ KitManagerConfigWidget *KitModel::widget(const QModelIndex &index)
if (!index.isValid())
return 0;
KitNode *node = static_cast<KitNode *>(index.internalPointer());
Q_ASSERT(node);
return node->widget;
}
@@ -284,10 +277,11 @@ void KitModel::apply()
Q_ASSERT(!n->parent);
n->widget->removeKit();
}
Q_ASSERT(m_toRemoveList.isEmpty());
// Update kits:
foreach (KitNode *n, m_manualRoot->childNodes) {
nodes = m_autoRoot->childNodes; // These can be dirty due to being made default!
nodes.append(m_manualRoot->childNodes);
foreach (KitNode *n, nodes) {
Q_ASSERT(n);
Q_ASSERT(n->widget);
if (n->widget->isDirty()) {
@@ -330,7 +324,9 @@ Kit *KitModel::markForAddition(Kit *baseKit)
KitNode *node = createNode(m_manualRoot, 0);
if (baseKit) {
Kit *k = node->widget->workingCopy();
KitGuard g(k);
k->copyFrom(baseKit);
k->setAutoDetected(false); // Make sure we have a manual kit!
k->setDisplayName(tr("Clone of %1").arg(k->displayName()));
}

View File

@@ -94,7 +94,6 @@ QWidget *KitOptionsPage::createPage(QWidget *parent)
QVBoxLayout *verticalLayout = new QVBoxLayout(m_configWidget);
verticalLayout->addLayout(horizontalLayout);
Q_ASSERT(!m_model);
m_model = new Internal::KitModel(verticalLayout);
connect(m_model, SIGNAL(kitStateChanged()), this, SLOT(updateState()));
verticalLayout->setStretch(0, 1);

View File

@@ -467,19 +467,19 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect()
tmp.append(new MsvcToolChain(generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::x86),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::x86, version),
fi.absoluteFilePath(), QLatin1String("/x86"), true));
// Add all platforms
// Add all platforms, cross-compiler is automatically selected by SetEnv.cmd if needed
tmp.append(new MsvcToolChain(generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::amd64),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::amd64, version),
fi.absoluteFilePath(), QLatin1String("/amd64"), true));
fi.absoluteFilePath(), QLatin1String("/x64"), true));
tmp.append(new MsvcToolChain(generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::x86_amd64),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::x86_amd64, version),
fi.absoluteFilePath(), QLatin1String("/x86_amd64"), true));
fi.absoluteFilePath(), QLatin1String("/x64"), true));
tmp.append(new MsvcToolChain(generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::ia64),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::ia64, version),
fi.absoluteFilePath(), QLatin1String("/ia64"), true));
tmp.append(new MsvcToolChain(generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::x86_ia64),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::x86_ia64, version),
fi.absoluteFilePath(), QLatin1String("/x86_ia64"), true));
fi.absoluteFilePath(), QLatin1String("/ia64"), true));
// Make sure the default is front.
if (folder == defaultSdkPath)
results = tmp + results;

View File

@@ -159,9 +159,15 @@ bool DebuggerRunConfigurationAspect::useCppDebugger() const
static bool isQtQuickAppProject(Project *project)
{
const QString filePath = project->projectDirectory()
const QString projectDirectory = project->projectDirectory();
// Qt Quick 1 wizard generated file
const QString qq1FilePath = projectDirectory
+ QLatin1String("/qmlapplicationviewer/qmlapplicationviewer.pri");
return project->files(Project::ExcludeGeneratedFiles).contains(filePath);
// Qt Quick 2 wizard generated file
const QString qq2FilePath = projectDirectory
+ QLatin1String("/qtquick2applicationviewer/qtquick2applicationviewer.pri");
const QStringList projectFiles = project->files(Project::ExcludeGeneratedFiles);
return projectFiles.contains(qq1FilePath) || projectFiles.contains(qq2FilePath);
}
bool DebuggerRunConfigurationAspect::useQmlDebugger() const

View File

@@ -210,6 +210,7 @@ NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceV
}
} else {
if (!hasQtQuick2(m_nodeInstanceView.data()))
QMessageBox::warning(0, tr("Cannot Start QML Puppet Executable"),
tr("The executable of the QML Puppet process (%1) cannot be started. "
"Please check your installation. "
@@ -220,6 +221,7 @@ NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceV
m_localServer->close();
} else {
if (!hasQtQuick2(m_nodeInstanceView.data()))
QMessageBox::warning(0, tr("Cannot Find QML Puppet Executable"),
tr("The executable of the QML Puppet process (%1) cannot be found. "
"Please check your installation. "

View File

@@ -79,7 +79,7 @@ Core::BaseFileWizardParameters QmlProjectApplicationWizard::parameters()
"QML file that contains the main view.\n\n"
"You can review Qt Quick UI projects in the QML Viewer and you need not build them. "
"You do not need to have the development environment installed "
"on your computer to create and run this type of project.\n\nRequires <b>Qt 4.7.4</b> or newer."));
"on your computer to create and run this type of projects.\n\nRequires <b>Qt 5.0</b> or newer."));
parameters.setCategory(QLatin1String(ProjectExplorer::Constants::QT_APPLICATION_WIZARD_CATEGORY));
parameters.setDisplayCategory(QT_TRANSLATE_NOOP("ProjectExplorer", "Qt Application"));
return parameters;
@@ -119,8 +119,7 @@ Core::GeneratedFiles QmlProjectApplicationWizard::generateFiles(const QWizard *w
QTextStream out(&contents);
out
<< "// import QtQuick 1.0 // to target Maemo 5" << endl
<< "import QtQuick 1.1" << endl
<< "import QtQuick 2.0" << endl
<< endl
<< "Rectangle {" << endl
<< " width: 360" << endl

View File

@@ -203,9 +203,12 @@ QStringList QMakeStep::deducedArguments()
if (!version->needsQmlDebuggingLibrary()) {
// This Qt version has the QML debugging services built in, however
// they still need to be enabled at compile time
arguments << (version->qtVersion().majorVersion >= 5 ?
QLatin1String(Constants::QMAKEVAR_DECLARATIVE_DEBUG5) :
QLatin1String(Constants::QMAKEVAR_DECLARATIVE_DEBUG4));
// TODO: For Qt5, we can pass both arguments as there can be Qt Quick 1/2 projects.
// Currently there is no support for debugging multiple engines.
arguments << QLatin1String(Constants::QMAKEVAR_QUICK1_DEBUG);
if (version->qtVersion().majorVersion >= 5) {
arguments << QLatin1String(Constants::QMAKEVAR_QUICK2_DEBUG);
}
} else {
const QString qmlDebuggingHelperLibrary = version->qmlDebuggingHelperLibrary(true);
if (!qmlDebuggingHelperLibrary.isEmpty()) {

View File

@@ -458,8 +458,8 @@ bool Qt4BuildConfiguration::removeQMLInspectorFromArguments(QString *args)
for (QtcProcess::ArgIterator ait(args); ait.next(); ) {
const QString arg = ait.value();
if (arg.contains(QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH))
|| arg.contains(QLatin1String(Constants::QMAKEVAR_DECLARATIVE_DEBUG4))
|| arg.contains(QLatin1String(Constants::QMAKEVAR_DECLARATIVE_DEBUG5))) {
|| arg.contains(QLatin1String(Constants::QMAKEVAR_QUICK1_DEBUG))
|| arg.contains(QLatin1String(Constants::QMAKEVAR_QUICK2_DEBUG))) {
ait.deleteArg();
removedArgument = true;
}

View File

@@ -89,8 +89,8 @@ const char ICON_HTML5_APP[] = ":/wizards/images/html5app.png";
// Env variables
const char QMAKEVAR_QMLJSDEBUGGER_PATH[] = "QMLJSDEBUGGER_PATH";
const char QMAKEVAR_DECLARATIVE_DEBUG4[] = "CONFIG+=declarative_debug";
const char QMAKEVAR_DECLARATIVE_DEBUG5[] = "CONFIG+=qml_debug";
const char QMAKEVAR_QUICK1_DEBUG[] = "CONFIG+=declarative_debug";
const char QMAKEVAR_QUICK2_DEBUG[] = "CONFIG+=qml_debug";
// Unconfigured Panel
const char UNCONFIGURED_PANEL_PAGE_ID[] = "UnconfiguredPanel";

View File

@@ -135,7 +135,7 @@ void QtQuickAppWizard::createInstances(ExtensionSystem::IPlugin *plugin)
QList<Core::BaseFileWizardParameters> list;
Core::BaseFileWizardParameters parameter;
const QString basicDescription = tr("Creates a Qt Quick application project that can contain "
const QString basicDescription = tr("Creates a Qt Quick 1 application project that can contain "
"both QML and C++ code and includes a QDeclarativeView.\n\n");
Core::FeatureSet basicFeatures;
@@ -151,7 +151,7 @@ void QtQuickAppWizard::createInstances(ExtensionSystem::IPlugin *plugin)
parameter = base;
parameter.setDisplayName(tr("Qt Quick 2 Application (Built-in Elements)"));
parameter.setDescription(tr("Creates a Qt Quick application project that can contain "
parameter.setDescription(tr("Creates a Qt Quick 2 application project that can contain "
"both QML and C++ code and includes a QQuickView.\n\n"
"The built-in elements in the QtQuick 2 namespace allow "
"you to write cross-platform applications with "
@@ -160,7 +160,7 @@ void QtQuickAppWizard::createInstances(ExtensionSystem::IPlugin *plugin)
list << parameter;
parameter = base;
parameter.setDisplayName(tr("Qt Quick Application for MeeGo Harmattan"));
parameter.setDisplayName(tr("Qt Quick 1 Application for MeeGo Harmattan"));
parameter.setDescription(basicDescription + tr("The Qt Quick Components for MeeGo Harmattan are "
"a set of ready-made components that are designed "
"with specific native appearance for the MeeGo Harmattan "
@@ -171,7 +171,7 @@ void QtQuickAppWizard::createInstances(ExtensionSystem::IPlugin *plugin)
list << parameter;
parameter = base;
parameter.setDisplayName(tr("Qt Quick Application (from Existing QML File)"));
parameter.setDisplayName(tr("Qt Quick 1 Application (from Existing QML File)"));
parameter.setDescription(basicDescription + tr("Creates a deployable Qt Quick application from "
"existing QML files. All files and directories that "
"reside in the same directory as the main .qml file "

View File

@@ -1189,49 +1189,69 @@ bool BaseQtVersion::queryQMakeVariables(const FileName &binary, const Utils::Env
return BaseQtVersion::queryQMakeVariables(binary, env, versionInfo, &qmakeIsExecutable);
}
bool BaseQtVersion::queryQMakeVariables(const FileName &binary, const Utils::Environment &env,
QHash<QString, QString> *versionInfo, bool *qmakeIsExecutable)
static QByteArray runQmakeQuery(const FileName &binary, const Environment &env,
bool *isExecutable)
{
const int timeOutMS = 30000; // Might be slow on some machines.
QProcess process;
process.setEnvironment(env.toStringList());
process.start(binary.toString(), QStringList(QLatin1String("-query")), QIODevice::ReadOnly);
if (!process.waitForStarted()) {
qWarning("Cannot start '%s': %s", qPrintable(binary.toUserOutput()), qPrintable(process.errorString()));
*isExecutable = false;
return QByteArray();
}
if (!process.waitForFinished(timeOutMS)) {
SynchronousProcess::stopProcess(process);
*isExecutable = true;
qWarning("Timeout running '%s' (%dms).", qPrintable(binary.toUserOutput()), timeOutMS);
return QByteArray();
}
if (process.exitStatus() != QProcess::NormalExit) {
qWarning("'%s' crashed.", qPrintable(binary.toUserOutput()));
*isExecutable = false;
return QByteArray();
}
*isExecutable = true;
return process.readAllStandardOutput();
}
bool BaseQtVersion::queryQMakeVariables(const FileName &binary, const Environment &env,
QHash<QString, QString> *versionInfo, bool *qmakeIsExecutable)
{
const QFileInfo qmake = binary.toFileInfo();
*qmakeIsExecutable = qmake.exists() && qmake.isExecutable() && !qmake.isDir();
if (!*qmakeIsExecutable)
return false;
QProcess process;
Environment qmakeEnv = env;
QByteArray output;
output = runQmakeQuery(binary, env, qmakeIsExecutable);
if (HostOsInfo::isWindowsHost()) {
// Add tool chain environment. This is necessary for non-static qmakes e.g. using mingw on windows
// We can not just add all the environments of all tool chains since that will make PATH too long
// which in turn will trigger a crash when parsing the results of vcvars.bat of MSVC.
if (output.isNull() && !qmakeIsExecutable) {
// Note: Don't rerun if we were able to execute the binary before.
// Try running qmake with all kinds of tool chains set up in the environment.
// This is required to make non-static qmakes work on windows where every tool chain
// tries to be incompatible with any other.
QList<ProjectExplorer::Abi> abiList = ProjectExplorer::Abi::abisOfBinary(binary);
QList<ProjectExplorer::ToolChain *> tcList = ProjectExplorer::ToolChainManager::instance()->toolChains();
foreach (ProjectExplorer::ToolChain *tc, tcList) {
if (abiList.contains(tc->targetAbi()))
tc->addToEnvironment(qmakeEnv);
if (!abiList.contains(tc->targetAbi()))
continue;
Environment realEnv = env;
tc->addToEnvironment(realEnv);
output = runQmakeQuery(binary, realEnv, qmakeIsExecutable);
if (qmakeIsExecutable)
break;
}
}
process.setEnvironment(qmakeEnv.toStringList());
process.start(qmake.absoluteFilePath(), QStringList(QLatin1String("-query")), QIODevice::ReadOnly);
if (output.isNull())
return false;
if (!process.waitForStarted()) {
*qmakeIsExecutable = false;
qWarning("Cannot start '%s': %s", qPrintable(binary.toUserOutput()), qPrintable(process.errorString()));
return false;
}
if (!process.waitForFinished(timeOutMS)) {
SynchronousProcess::stopProcess(process);
qWarning("Timeout running '%s' (%dms).", qPrintable(binary.toUserOutput()), timeOutMS);
return false;
}
if (process.exitStatus() != QProcess::NormalExit) {
*qmakeIsExecutable = false;
qWarning("'%s' crashed.", qPrintable(binary.toUserOutput()));
return false;
}
QByteArray output = process.readAllStandardOutput();
QTextStream stream(&output);
while (!stream.atEnd()) {
const QString line = stream.readLine();

View File

@@ -40,6 +40,9 @@
#include <qtsupport/qtversionmanager.h>
#include <utils/qtcassert.h>
#include <utils/environment.h>
#include <projectexplorer/kitmanager.h>
#include <qtsupport/qtkitinformation.h>
#include <algorithm>
using QtSupport::QtVersionManager;
@@ -309,6 +312,16 @@ QStringList ExamplesListModel::exampleSources(QString *examplesFallback, QString
QStringList sources;
QString resourceDir = Core::ICore::resourcePath() + QLatin1String("/welcomescreen/");
// overriding examples with a custom XML file
QString exampleFileEnvKey = QLatin1String("QTC_EXAMPLE_FILE");
if (Utils::Environment::systemEnvironment().hasKey(exampleFileEnvKey)) {
QString filePath = Utils::Environment::systemEnvironment().value(exampleFileEnvKey);
if (filePath.endsWith(QLatin1String(".xml")) && QFileInfo(filePath).exists()) {
sources.append(filePath);
return sources;
}
}
// Qt Creator shipped tutorials
sources << (resourceDir + QLatin1String("/qtcreator_tutorials.xml"));
@@ -331,11 +344,38 @@ QStringList ExamplesListModel::exampleSources(QString *examplesFallback, QString
QString potentialExamplesFallback;
QString potentialDemosFallback;
QString potentialSourceFallback;
bool potentialFallbackHasDeclarative = false; // we prefer Qt's with declarative as fallback
const QStringList pattern(QLatin1String("*.xml"));
// prioritize default qt version
QtVersionManager *versionManager = QtVersionManager::instance();
foreach (BaseQtVersion *version, versionManager->validVersions()) {
QList <BaseQtVersion *> qtVersions = versionManager->validVersions();
ProjectExplorer::Kit *defaultKit = ProjectExplorer::KitManager::instance()->defaultKit();
BaseQtVersion *defaultVersion = QtKitInformation::qtVersion(defaultKit);
if (defaultVersion && qtVersions.contains(defaultVersion))
qtVersions.move(qtVersions.indexOf(defaultVersion), 0);
foreach (BaseQtVersion *version, qtVersions) {
// qt5 with examples OR demos manifest
if (version->qtVersion().majorVersion == 5 && (version->hasExamples() || version->hasDemos())) {
// examples directory in Qt5 is under the qtbase submodule,
// search other submodule directories for further manifest files
QDir qt5docPath = QDir(version->documentationPath());
const QStringList examplesPattern(QLatin1String("examples-manifest.xml"));
const QStringList demosPattern(QLatin1String("demos-manifest.xml"));
QFileInfoList fis;
foreach (QFileInfo subDir, qt5docPath.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) {
if (version->hasExamples())
fis << QDir(subDir.absoluteFilePath()).entryInfoList(examplesPattern);
if (version->hasDemos())
fis << QDir(subDir.absoluteFilePath()).entryInfoList(demosPattern);
}
if (!fis.isEmpty()) {
foreach (const QFileInfo &fi, fis)
sources.append(fi.filePath());
return sources;
}
}
QFileInfoList fis;
if (version->hasExamples())
fis << QDir(version->examplesPath()).entryInfoList(pattern);
@@ -346,13 +386,9 @@ QStringList ExamplesListModel::exampleSources(QString *examplesFallback, QString
sources.append(fi.filePath());
return sources;
}
// check if this Qt version would be the preferred fallback, Qt 4 only
if (version->qtVersion().majorVersion == 4 && version->hasExamples() && version->hasDemos()) { // cached, so no performance hit
bool hasDeclarative = QDir(version->examplesPath() + QLatin1String("/declarative")).exists();
if (potentialExamplesFallback.isEmpty()
|| (!potentialFallbackHasDeclarative && hasDeclarative)) {
potentialFallbackHasDeclarative = hasDeclarative;
if (potentialExamplesFallback.isEmpty()) {
potentialExamplesFallback = version->examplesPath();
potentialDemosFallback = version->demosPath();
potentialSourceFallback = version->sourcePath().toString();

View File

@@ -44,6 +44,8 @@
#include <Overview.h>
#include <LookupContext.h>
#include "cplusplus-tools-utils.h"
#include <QFile>
#include <QList>
#include <QCoreApplication>
@@ -422,17 +424,49 @@ protected:
}
};
void printUsage()
{
std::cout << "Usage: " << qPrintable(QFileInfo(qApp->arguments().at(0)).fileName())
<< " [-v] [path to AST.h]\n\n"
<< "Print a visitor class based on AST.h to stdout.\n\n";
const QString defaulPath = QFileInfo(PATH_AST_H).canonicalFilePath();
std::cout << "Default path: " << qPrintable(defaulPath) << '.' << "\n";
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QStringList args = app.arguments();
args.removeFirst();
QStringList files = app.arguments();
files.removeFirst();
bool optionVerbose = false;
foreach (const QString &fileName, files) {
QFile file(fileName);
if (! file.open(QFile::ReadOnly))
continue;
// Process options & arguments
if (args.contains("-v")) {
optionVerbose = true;
args.removeOne("-v");
}
const bool helpRequested = args.contains("-h") || args.contains("-help");
if (helpRequested || args.count() >= 2) {
printUsage();
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
}
// Run the preprocessor
QString fileName = PATH_AST_H;
if (!args.isEmpty())
fileName = args.first();
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
CplusplusToolsUtils::SystemPreprocessor preprocessor(optionVerbose);
preprocessor.preprocessFile(fileName, fileNamePreprocessed);
QFile file(fileNamePreprocessed);
if (! file.open(QFile::ReadOnly)) {
std::cerr << "Error: Could not open file \"" << qPrintable(file.fileName()) << "\"."
<< std::endl;
return EXIT_FAILURE;
}
const QByteArray source = file.readAll();
file.close();
@@ -441,16 +475,14 @@ int main(int argc, char *argv[])
//doc->control()->setDiagnosticClient(0);
doc->setUtf8Source(source);
doc->parse();
doc->translationUnit()->blockErrors(true);
doc->check();
Snapshot snapshot;
snapshot.insert(doc);
LookupContext context(doc, snapshot);
MkVisitor mkVisitor(context);
}
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,13 @@
QT = core gui
macx:CONFIG -= app_bundle
win32:CONFIG += console
TEMPLATE = app
TARGET = cplusplus-mkvisitor
DESTDIR = ./
include(../../../qtcreator.pri)
include(../../libs/cplusplus/cplusplus-lib.pri)
include(../../../src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri)
DEFINES += PATH_AST_H=\\\"$$PWD/../../libs/3rdparty/cplusplus/AST.h\\\"
SOURCES += cplusplus-mkvisitor.cpp

View File

@@ -0,0 +1,140 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "cplusplus-tools-utils.h"
#include "environment.h"
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QProcess>
namespace CplusplusToolsUtils {
QString portableExecutableName(const QString &executable)
{
#if defined(Q_OS_WIN)
return executable + QLatin1String(".exe");
#else
return executable;
#endif
}
void executeCommand(const QString &command, const QStringList &arguments, const QString &outputFile,
bool verbose)
{
QTextStream out(stderr);
if (command.isEmpty()) {
out << "Error: " << Q_FUNC_INFO << "Got empty command to execute." << endl;
exit(EXIT_FAILURE);
}
const QString fullCommand = command + QLatin1Char(' ') + arguments.join(QLatin1String(" "));
if (verbose)
out << "Executing: " << fullCommand << endl;
QProcess process;
if (!outputFile.isEmpty())
process.setStandardOutputFile(outputFile, QIODevice::Truncate);
process.start(command, arguments);
if (!process.waitForStarted()) {
out << QString("Error: Process \"%1\" did not start within timeout: %2.")
.arg(fullCommand, process.errorString())
<< endl;
exit(EXIT_FAILURE);
}
if (!process.waitForFinished()) {
if (!verbose)
out << process.readAll() << endl;
out << QString("Error: Process \"%1\" did not finish within timeout.").arg(fullCommand)
<< endl;
exit(EXIT_FAILURE);
}
const int exitCode = process.exitCode();
if (exitCode != 0) {
out << process.readAllStandardError() << endl;
out << QString("Error: Process \"%1\" finished with non zero exit value %2")
.arg(fullCommand, exitCode) << endl;
exit(EXIT_FAILURE);
}
}
SystemPreprocessor::SystemPreprocessor(bool verbose)
: m_verbose(verbose)
{
m_knownCompilers[portableExecutableName("gcc")]
= QLatin1String("-DCPLUSPLUS_WITHOUT_QT -U__BLOCKS__ -xc++ -E -include");
m_knownCompilers[portableExecutableName("cl")]
= QLatin1String("/DCPLUSPLUS_WITHOUT_QT /U__BLOCKS__ /TP /E /I . /FI");
QMapIterator<QString, QString> i(m_knownCompilers);
while (i.hasNext()) {
i.next();
const QString executablePath
= Utils::Environment::systemEnvironment().searchInPath(i.key());
if (!executablePath.isEmpty()) {
m_compiler = i.key();
m_compilerArguments = i.value().split(QLatin1String(" "), QString::SkipEmptyParts);
m_compilerArguments
<< QDir::toNativeSeparators(QLatin1String(PATH_PREPROCESSOR_CONFIG));
break;
}
}
}
void SystemPreprocessor::check() const
{
QTextStream out(stderr);
if (!QFile::exists(PATH_PREPROCESSOR_CONFIG)) {
out << QString("Error: File \"%1\" does not exist.").arg(PATH_PREPROCESSOR_CONFIG) << endl;
exit(EXIT_FAILURE);
}
if (m_compiler.isEmpty()) {
const QString triedCompilers
= QStringList(m_knownCompilers.keys()).join(QLatin1String(", "));
out << QString("Error: No compiler found. Tried %1.").arg(triedCompilers) << endl;
exit(EXIT_FAILURE);
}
}
void SystemPreprocessor::preprocessFile(const QString &inputFile, const QString &outputFile) const
{
check();
if (!QFile::exists(inputFile)) {
QTextStream out(stderr);
out << QString("Error: File \"%1\" does not exist.").arg(inputFile) << endl;
exit(EXIT_FAILURE);
}
const QStringList arguments = QStringList(m_compilerArguments)
<< QDir::toNativeSeparators(inputFile);
executeCommand(m_compiler, arguments, outputFile, m_verbose);
}
} // namespace

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CPLUSPLUSTOOLSUTILS_H
#define CPLUSPLUSTOOLSUTILS_H
#include <QString>
#include <QStringList>
#include <QMap>
namespace CplusplusToolsUtils {
QString portableExecutableName(const QString &executable);
void executeCommand(const QString &command, const QStringList &arguments, const QString &outputFile,
bool verbose = false);
// Preprocess a file by calling an external compiler in preprocessor mode (-E, /E).
class SystemPreprocessor
{
public:
SystemPreprocessor(bool verbose = false);
void preprocessFile(const QString &inputFile, const QString &outputFile) const;
private:
void check() const;
QMap<QString, QString> m_knownCompilers;
QString m_compiler; // Compiler that will be called in preprocessor mode
QStringList m_compilerArguments;
bool m_verbose;
};
} // namespace
#endif // CPLUSPLUSTOOLSUTILS_H

View File

@@ -0,0 +1,13 @@
DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD $$PWD/../../libs/utils
DEFINES += PATH_PREPROCESSOR_CONFIG=\\\"$$PWD/pp-configuration.inc\\\"
DEFINES += QTCREATOR_UTILS_STATIC_LIB
HEADERS += \
$$PWD/cplusplus-tools-utils.h \
$$PWD/../../libs/utils/environment.h
SOURCES += \
$$PWD/cplusplus-tools-utils.cpp \
$$PWD/../../libs/utils/environment.cpp

View File

@@ -1,15 +1,17 @@
#define __extension__
#define __context__
#define __range__
#define __asm(a...)
#define __asm__(a...)
#if !defined(_WIN32) && !defined(_WIN64)
# define __asm(a...)
# define __asm__(a...)
# define __stdcall
# define __fastcall
#endif
#define restrict
#define __restrict
#define __restrict__
// #define __weak
#define __builtin_va_arg(a,b) ((b)0)
#define __stdcall
#define __fastcall
#define __imag__
#define __real__
#define __complex__

View File

@@ -91,12 +91,21 @@ static const char generatedHeader[] =
"// W A R N I N G\n"
"// -------------\n"
"//\n"
"// This file is automatically generated.\n"
"// This file is automatically generated by \"cplusplus-update-frontend\".\n"
"// Changes will be lost.\n"
"//\n"
"\n"
;
static void closeAndPrintFilePath(QFile &file)
{
if (file.isOpen()) {
const QString filePath = QFileInfo(file).canonicalFilePath();
std::cout << QDir::toNativeSeparators(filePath).toLatin1().constData() << std::endl;
file.close();
}
}
class ASTNodes
{
public:
@@ -226,6 +235,8 @@ public:
"using namespace CPlusPlus;\n" << endl;
accept(ast);
closeAndPrintFilePath(file);
}
protected:
@@ -354,7 +365,6 @@ public:
QTextStream output(&file);
out = &output;
*out << copyrightHeader << generatedHeader <<
"\n"
"#include \"AST.h\"\n"
@@ -363,6 +373,8 @@ public:
"using namespace CPlusPlus;\n" << endl;
accept(ast);
closeAndPrintFilePath(file);
}
protected:
@@ -480,6 +492,8 @@ public:
<< endl;
accept(ast);
closeAndPrintFilePath(file);
}
protected:
@@ -627,7 +641,7 @@ public:
accept(ast);
file.close();
closeAndPrintFilePath(file);
}
protected:
@@ -761,7 +775,7 @@ public:
d.accept(unit->ast());
file.close();
closeAndPrintFilePath(file);
}
protected:
@@ -1220,6 +1234,7 @@ void generateAST_cpp(const Snapshot &snapshot, const QDir &cplusplusDir)
if (file.open(QFile::WriteOnly)) {
QTextStream out(&file);
out << cpp_document.toPlainText();
closeAndPrintFilePath(file);
}
}
@@ -1312,6 +1327,8 @@ void generateASTVisitor_H(const Snapshot &, const QDir &cplusplusDir,
"} // namespace CPlusPlus\n"
"\n"
"#endif // CPLUSPLUS_ASTVISITOR_H\n";
closeAndPrintFilePath(file);
}
void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
@@ -1353,6 +1370,8 @@ void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
"} // namespace CPlusPlus\n"
"\n"
"#endif // CPLUSPLUS_ASTMATCHER_H\n";
closeAndPrintFilePath(file);
}
QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, const QString &dumpersFile)
@@ -1437,6 +1456,7 @@ QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, co
if (file.open(QFile::WriteOnly)) {
QTextStream out(&file);
out << document.toPlainText();
closeAndPrintFilePath(file);
}
Accept0CG cg(cplusplusDir, AST_h_document->translationUnit());
@@ -1537,6 +1557,7 @@ void generateASTFwd_h(const Snapshot &snapshot, const QDir &cplusplusDir, const
if (file.open(QFile::WriteOnly)) {
QTextStream out(&file);
out << document.toPlainText();
closeAndPrintFilePath(file);
}
}
@@ -1664,36 +1685,67 @@ void generateASTPatternBuilder_h(const QDir &cplusplusDir)
<< "} // end of namespace CPlusPlus" << endl
<< endl
<< "#endif // CPLUSPLUS_AST_PATTERN_BUILDER_H" << endl;
closeAndPrintFilePath(file);
}
void printUsage()
{
const QByteArray executable = QFileInfo(qApp->arguments().first()).fileName().toLatin1();
std::cout << "Usage: " << executable.constData() << "\n"
<< " " << executable.constData() << " <frontend-dir> <dumpers-file>"
<< "\n\n"
<< "Generate appropriate header and source files of the C++ frontend accordingly\n"
<< "to AST.h and print the paths of the written files. Run this tool after\n"
<< "modifying AST.h."
<< "\n\n";
const QString defaultPathCppFrontend = QFileInfo(PATH_CPP_FRONTEND).canonicalFilePath();
const QString defaultPathDumpersFile = QFileInfo(PATH_DUMPERS_FILE).canonicalFilePath();
std::cout << "Default values:" << "\n"
<< " frontend-dir: " << qPrintable(defaultPathCppFrontend) << "\n"
<< " dumpers-file: " << qPrintable(defaultPathDumpersFile) << "\n";
}
int main(int argc, char *argv[])
{
MyQApplication app(argc, argv);
QStringList args = app.arguments();
args.removeFirst();
QStringList files = app.arguments();
files.removeFirst();
QString pathCppFrontend = PATH_CPP_FRONTEND;
QString pathDumpersFile = PATH_DUMPERS_FILE;
if (files.size() != 1 && files.size() != 2) {
std::cerr << "Usage: cplusplus [path to C++ front-end]" << std::endl;
std::cerr << " or: cplusplus [path to C++ front-end] [dumpers file name]" << std::endl;
return EXIT_FAILURE;
const bool helpRequested = args.contains("-h") || args.contains("-help");
if (args.count() == 1 || args.count() >= 3 || helpRequested) {
printUsage();
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
} else if (args.count() == 2) {
pathCppFrontend = args.at(0);
pathDumpersFile = args.at(1);
}
QDir cplusplusDir(files.first());
QDir cplusplusDir(pathCppFrontend);
if (!QFile::exists(pathCppFrontend)) {
std::cerr << "Error: Directory \"" << qPrintable(cplusplusDir.absolutePath())
<< "\" does not exist." << std::endl;
return EXIT_FAILURE;
}
if (!QFileInfo(cplusplusDir, QLatin1String("AST.h")).exists()) {
std::cerr << "Cannot find AST.h in " << qPrintable(cplusplusDir.absolutePath())
<< std::endl;
std::cerr << "Error: Cannot find AST.h in \"" << qPrintable(cplusplusDir.absolutePath())
<< "\"." << std::endl;
return EXIT_FAILURE;
}
if (!QFile::exists(pathDumpersFile)) {
std::cerr << "Error: File \"" << qPrintable(pathDumpersFile)
<< "\" does not exist." << std::endl;
return EXIT_FAILURE;
}
QString dumpersFile;
if (files.size() == 2)
dumpersFile = files.last();
Snapshot snapshot;
QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, dumpersFile);
QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, pathDumpersFile);
astDerivedClasses.sort();
generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses);
generateASTPatternBuilder_h(cplusplusDir);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,15 @@
QT = core gui
macx:CONFIG -= app_bundle
win32:CONFIG += console
TEMPLATE = app
TARGET = cplusplus-update-frontend
DESTDIR = ./
DEFINES += QTCREATOR_UTILS_STATIC_LIB
INCLUDEPATH += . ../../libs
include(../../../qtcreator.pri)
include(../../libs/cplusplus/cplusplus-lib.pri)
DEFINES += PATH_CPP_FRONTEND=\\\"$$PWD/../../libs/3rdparty/cplusplus\\\"
DEFINES += PATH_DUMPERS_FILE=\\\"$$PWD/../../../tests/tools/cplusplus-ast2png/dumpers.inc\\\"
SOURCES += cplusplus-update-frontend.cpp ../../libs/utils/changeset.cpp

View File

@@ -1,10 +0,0 @@
QT = core gui
macx:CONFIG -= app_bundle
TEMPLATE = app
TARGET = generate-ast
INCLUDEPATH += . ../../libs
include(../../libs/cplusplus/cplusplus-lib.pri)
# Input
SOURCES += generate-ast.cpp ../../libs/utils/changeset.cpp

View File

@@ -1,15 +0,0 @@
#define __extension__
#define __context__
#define __range__
#define __asm(a...)
#define __asm__(a...)
#define restrict
#define __restrict
#define __restrict__
// #define __weak
#define __builtin_va_arg(a,b) ((b)0)
#define __stdcall
#define __fastcall
#define __imag__
#define __real__
#define __complex__

View File

@@ -1,5 +0,0 @@
#!/bin/sh
me=$(dirname $0)
${CPP-gcc} -DCPLUSPLUS_WITHOUT_QT -U__BLOCKS__ -xc++ -E -include $me/conf.c++ ../../libs/3rdparty/cplusplus/AST.h > $me/file.i
$me/cplusplus0 $me/file.i
rm -f $me/file.i

View File

@@ -1,20 +0,0 @@
QT = core gui
macx:CONFIG -= app_bundle
TARGET = cplusplus0
INCLUDEPATH += . ../../libs
include(../../libs/cplusplus/cplusplus-lib.pri)
# Input
SOURCES += main.cpp
unix {
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
RCC_DIR = $${OUT_PWD}/.rcc/
UI_DIR = $${OUT_PWD}/.uic/
}

View File

@@ -349,6 +349,10 @@ QVariantMap AddKitOperation::addKit(const QVariantMap &map,
nameList << GetOperation::get(map, nameKey).toString();
const QString uniqueName = makeUnique(displayName, nameList);
QString qtId = qt;
if (!qtId.startsWith(QLatin1String("SDK.")))
qtId = QString::fromLatin1("SDK.") + qt;
// insert data:
KeyValuePairList data;
data << KeyValuePair(QStringList() << kit << QLatin1String(ID), QVariant(id));
@@ -363,7 +367,7 @@ QVariantMap AddKitOperation::addKit(const QVariantMap &map,
data << KeyValuePair(QStringList() << kit << QLatin1String(DATA) << DEVICE_TYPE, QVariant(deviceType));
data << KeyValuePair(QStringList() << kit << QLatin1String(DATA) << SYSROOT, QVariant(sysRoot));
data << KeyValuePair(QStringList() << kit << QLatin1String(DATA) << TOOLCHAIN, QVariant(tc));
data << KeyValuePair(QStringList() << kit << QLatin1String(DATA) << QT, QVariant(qt));
data << KeyValuePair(QStringList() << kit << QLatin1String(DATA) << QT, QVariant(qtId));
data << KeyValuePair(QStringList() << kit << QLatin1String(DATA) << MKSPEC, QVariant(mkspec));
data << KeyValuePair(QStringList() << QLatin1String(DEFAULT), QVariant(defaultKit));

View File

@@ -37,6 +37,8 @@
#include "settings.h"
#include <QDir>
#include <iostream>
// Qt version file stuff:
@@ -172,9 +174,15 @@ bool AddQtOperation::test() const
|| map.value(QLatin1String(VERSION)).toInt() != 1)
return false;
#if defined Q_OS_WIN
map = addQt(map, QLatin1String("testId"), QLatin1String("Test Qt Version"), QLatin1String("testType"),
QLatin1String("/tmp/test/qmake"),
QLatin1String("/tmp//../tmp/test\\qmake"),
KeyValuePairList() << KeyValuePair(QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))));
#else
map = addQt(map, QLatin1String("testId"), QLatin1String("Test Qt Version"), QLatin1String("testType"),
QLatin1String("/tmp//../tmp/test/qmake"),
KeyValuePairList() << KeyValuePair(QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))));
#endif
if (map.count() != 2
|| !map.contains(QLatin1String(VERSION))
@@ -247,8 +255,12 @@ QVariantMap AddQtOperation::addQt(const QVariantMap &map,
const QString &id, const QString &displayName, const QString &type,
const QString &qmake, const KeyValuePairList &extra)
{
QString sdkId = id;
if (!id.startsWith(QLatin1String("SDK.")))
sdkId = QString::fromLatin1("SDK.") + id;
// Sanity check: Make sure autodetection source is not in use already:
QStringList valueKeys = FindValueOperation::findValues(map, id);
QStringList valueKeys = FindValueOperation::findValues(map, sdkId);
bool hasId = false;
foreach (const QString &k, valueKeys) {
if (k.endsWith(QString(QLatin1Char('/')) + QLatin1String(AUTODETECTION_SOURCE))) {
@@ -281,13 +293,16 @@ QVariantMap AddQtOperation::addQt(const QVariantMap &map,
nameList << GetOperation::get(map, nameKey).toString();
const QString uniqueName = makeUnique(displayName, nameList);
// Sanitize qmake path:
QString saneQmake = QDir::cleanPath(QDir::fromNativeSeparators(qmake));
// insert data:
KeyValuePairList data;
data << KeyValuePair(QStringList() << qt << QLatin1String(ID), QVariant(-1));
data << KeyValuePair(QStringList() << qt << QLatin1String(DISPLAYNAME), QVariant(uniqueName));
data << KeyValuePair(QStringList() << qt << QLatin1String(AUTODETECTED), QVariant(true));
data << KeyValuePair(QStringList() << qt << QLatin1String(AUTODETECTION_SOURCE), QVariant(id));
data << KeyValuePair(QStringList() << qt << QLatin1String(QMAKE), QVariant(qmake));
data << KeyValuePair(QStringList() << qt << QLatin1String(AUTODETECTION_SOURCE), QVariant(sdkId));
data << KeyValuePair(QStringList() << qt << QLatin1String(QMAKE), QVariant(saneQmake));
data << KeyValuePair(QStringList() << qt << QLatin1String(TYPE), QVariant(type));
KeyValuePairList qtExtraList;

View File

@@ -87,7 +87,7 @@ int RmQtOperation::execute() const
if (result == map)
return -2;
return save(map, QLatin1String("qtversion")) ? 0 : -3;
return save(result, QLatin1String("qtversion")) ? 0 : -3;
}
#ifdef WITH_TESTS
@@ -133,12 +133,17 @@ bool RmQtOperation::test() const
QVariantMap RmQtOperation::rmQt(const QVariantMap &map, const QString &id)
{
QString sdkId = id;
if (!id.startsWith(QLatin1String("SDK.")))
sdkId = QString::fromLatin1("SDK.") + id;
QVariantList qtList;
for (QVariantMap::const_iterator i = map.begin(); i != map.end(); ++i) {
if (!i.key().startsWith(QLatin1String(PREFIX)))
continue;
QVariantMap qtData = i.value().toMap();
if (qtData.value(QLatin1String(AUTODETECTION_SOURCE)).toString() != id)
const QString dataId = qtData.value(QLatin1String(AUTODETECTION_SOURCE)).toString();
if ((dataId != id) && (dataId != sdkId))
qtList.append(qtData);
}

View File

@@ -1,5 +0,0 @@
#!/bin/sh
me=$(dirname $0)
${CPP-gcc} -U__BLOCKS__ -xc++ -E -include $me/conf.c++ $* > $me/file.i
$me/cplusplus0 $me/file.i

View File

@@ -40,6 +40,8 @@
#include <CoreTypes.h>
#include <CppDocument.h>
#include "cplusplus-tools-utils.h"
#include <QFile>
#include <QList>
#include <QCoreApplication>
@@ -54,18 +56,47 @@
using namespace CPlusPlus;
void printUsage()
{
std::cout << "Usage: " << qPrintable(QFileInfo(qApp->arguments().at(0)).fileName())
<< " [-v] <file1> <file2> ...\n\n"
<< "Run the parser with the given files.\n";
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QStringList args = app.arguments();
args.removeFirst();
QStringList files = app.arguments();
files.removeFirst();
bool optionVerbose = false;
// Process options & arguments
if (args.contains("-v")) {
optionVerbose = true;
args.removeOne("-v");
}
const bool helpRequested = args.contains("-h") || args.contains("-help");
if (args.isEmpty() || helpRequested) {
printUsage();
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
}
// Process files
const QStringList files = args;
foreach (const QString &fileName, files) {
QFile file(fileName);
if (! file.open(QFile::ReadOnly))
continue;
// Run preprocessor
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
CplusplusToolsUtils::SystemPreprocessor preprocessor(optionVerbose);
preprocessor.preprocessFile(fileName, fileNamePreprocessed);
// Run parser
QFile file(fileNamePreprocessed);
if (! file.open(QFile::ReadOnly)) {
std::cerr << "Error: Could not open file \"" << qPrintable(file.fileName()) << "\"."
<< std::endl;
return EXIT_FAILURE;
}
const QByteArray source = file.readAll();
file.close();

View File

@@ -1,21 +1,13 @@
QT = core gui
macx:CONFIG -= app_bundle
TARGET = cplusplus0
win32:CONFIG += console
TEMPLATE = app
TARGET = cplusplus-frontend
DESTDIR = ./
include(../../../qtcreator.pri)
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri)
include($$IDE_SOURCE_TREE/src/libs/languageutils/languageutils.pri)
include($$IDE_SOURCE_TREE/src/libs/utils/utils.pri)
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus-lib.pri)
include($$IDE_SOURCE_TREE/tests/auto/qttestrpath.pri)
include(../../../src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri)
# Input
SOURCES += main.cpp
unix {
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
RCC_DIR = $${OUT_PWD}/.rcc/
UI_DIR = $${OUT_PWD}/.uic/
}
SOURCES += cplusplus-frontend.cpp

View File

@@ -89,12 +89,12 @@
#if !(USE_AUTOBREAK)
#undef USE_AUTOBREAK
#define USE_AUTOBREAK 1
#warning Switching on USE_AUTOBREAK
#pragma message ("Switching on USE_AUTOBREAK")
#endif // !USE_AUTOBREAK
#if USE_UNINITIALIZED_AUTOBREAK
#undef USE_UNINITIALIZED_AUTOBREAK
#define USE_UNINITIALIZED_AUTOBREAK 0
#warning Switching off USE_AUTOBREAK
#pragma message ("Switching off USE_UNINITIALIZED_AUTOBREAK")
#endif // USE_UNINITIALIZED_AUTOBREAK
#endif

View File

@@ -204,7 +204,7 @@ def __getTargetFromToolTip__(toolTip):
if toolTip == None or not isinstance(toolTip, (str, unicode)):
test.warning("Parameter toolTip must be of type str or unicode and can't be None!")
return None
pattern = re.compile(".*<b>Target:</b>(.*)<b>Deploy.*")
pattern = re.compile(".*<b>Kit:</b>(.*)<b>Deploy.*")
target = pattern.match(toolTip)
if target == None:
test.fatal("UI seems to have changed - expected ToolTip does not match.",

View File

@@ -42,6 +42,10 @@ def main():
else:
pos = size
if key == "<Left>":
if platform.system() == "Darwin":
# native cursor behavior on Mac is different
pos = 0
else:
pos -= 1
test.compare(editor.textCursor().selectionStart(), pos)
test.compare(editor.textCursor().selectionEnd(), pos)

View File

@@ -42,6 +42,9 @@
#include <SymbolVisitor.h>
#include <Overview.h>
#include "cplusplus-tools-utils.h"
#include <QDir>
#include <QFile>
#include <QList>
#include <QCoreApplication>
@@ -58,6 +61,22 @@
# include <cxxabi.h>
#endif
// For isatty(), _isatty()
#if defined(Q_OS_WIN)
# include <io.h>
#else
# include <unistd.h>
#endif
bool tty_for_stdin()
{
#if defined(Q_OS_WIN)
return _isatty(_fileno(stdin));
#else
return isatty(fileno(stdin));
#endif
}
using namespace CPlusPlus;
class ASTDump: protected ASTVisitor
@@ -68,9 +87,6 @@ public:
void operator()(AST *ast) {
QByteArray basename = translationUnit()->fileName();
int dotIdx = basename.lastIndexOf('.');
if (dotIdx != -1)
basename.truncate(dotIdx);
basename.append(".ast.dot");
out.open(basename.constData());
@@ -89,11 +105,10 @@ public:
out << "}" << std::endl;
out.close();
std::cout << basename.constData() << std::endl;
}
// the following file can be generated by using:
// generate-ast <path to cpp stuff> <path to dumpers.inc>
// cplusplus-update-frontend <frontend-dir> <dumpers-file>
#include "dumpers.inc"
protected:
@@ -195,9 +210,6 @@ public:
void operator()(Symbol *s) {
QByteArray basename = translationUnit->fileName();
int dotIdx = basename.lastIndexOf('.');
if (dotIdx != -1)
basename.truncate(dotIdx);
basename.append(".symbols.dot");
out.open(basename.constData());
@@ -218,7 +230,6 @@ public:
out << "}" << std::endl;
out.close();
std::cout << basename.constData() << std::endl;
}
protected:
@@ -351,19 +362,103 @@ private:
Overview o;
};
void createImageFromDot(const QString &inputFile, const QString &outputFile, bool verbose)
{
const QString command = CplusplusToolsUtils::portableExecutableName(QLatin1String("dot"));
const QStringList arguments = QStringList()
<< QLatin1String("-Tpng") << QLatin1String("-o") << outputFile << inputFile;
CplusplusToolsUtils::executeCommand(command, arguments, QString(), verbose);
}
const char PATH_STDIN_FILE[] = "_stdincontents.cpp";
QString example()
{
return
#if defined(Q_OS_WIN)
QString::fromLatin1("> echo int foo() {} | %1 && %2.ast.png")
#elif defined(Q_OS_MAC)
QString::fromLatin1("$ echo \"int foo() {}\" | ./%1 && open %2.ast.png")
#else
QString::fromLatin1("$ echo \"int foo() {}\" | ./%1 && xdg-open %2.ast.png")
#endif
.arg(QFileInfo(qApp->arguments().at(0)).fileName(), PATH_STDIN_FILE);
}
void printUsage()
{
std::cout << "Usage: " << qPrintable(QFileInfo(qApp->arguments().at(0)).fileName())
<< " [-v] <file1> <file2> ...\n\n";
std::cout << qPrintable(QString::fromLatin1(
"Visualize AST and symbol hierarchy of given C++ files by generating png image files\n"
"in the same directory as the input files. Print paths to generated image files.\n"
"\n"
"Standard input is also read. The resulting files starts with \"%1\"\n"
"and are created in the current working directory. To show the AST for simple snippets\n"
"you might want to execute:\n"
"\n"
" %2\n"
"\n"
"Prerequisites:\n"
" 1) Make sure to have 'dot' from graphviz locatable by PATH.\n"
" 2) Make sure to have an up to date dumpers file by using 'cplusplus-update-frontend'.\n"
).arg(PATH_STDIN_FILE, example()));
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QStringList args = app.arguments();
args.removeFirst();
QStringList files = app.arguments();
files.removeFirst();
bool optionVerbose = false;
// Data from stdin?
if (!tty_for_stdin()) {
QFile file("_stdincontents.cpp");
if (! file.open(QFile::WriteOnly)) {
std::cerr << "Error: Cannot open file for writing\"" << qPrintable(file.fileName())
<< "\"" << std::endl;
exit(EXIT_FAILURE);
}
file.write(QTextStream(stdin).readAll().toLocal8Bit());
file.close();
args.append(file.fileName());
}
// Process options & arguments
if (args.contains("-v")) {
optionVerbose = true;
args.removeOne("-v");
}
const bool helpRequested = args.contains("-h") || args.contains("-help");
if (args.isEmpty() || helpRequested) {
printUsage();
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
}
// Process files
const QStringList files = args;
foreach (const QString &fileName, files) {
QFile file(fileName);
if (! QFile::exists(fileName)) {
std::cerr << "Error: File \"" << qPrintable(fileName) << "\" does not exist."
<< std::endl;
exit(EXIT_FAILURE);
}
// Run the preprocessor
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
CplusplusToolsUtils::SystemPreprocessor preprocessor(optionVerbose);
preprocessor.preprocessFile(fileName, fileNamePreprocessed);
// Convert to dot
QFile file(fileNamePreprocessed);
if (! file.open(QFile::ReadOnly)) {
std::cerr << "Cannot open \"" << qPrintable(fileName)
<< "\", skipping it." << std::endl;
continue;
std::cerr << "Error: Could not open file \"" << qPrintable(fileNamePreprocessed)
<< "\"" << std::endl;
exit(EXIT_FAILURE);
}
const QByteArray source = file.readAll();
@@ -373,7 +468,6 @@ int main(int argc, char *argv[])
doc->control()->setDiagnosticClient(0);
doc->setUtf8Source(source);
doc->parse();
doc->check();
ASTDump dump(doc->translationUnit());
@@ -381,6 +475,18 @@ int main(int argc, char *argv[])
SymbolDump dump2(doc->translationUnit());
dump2(doc->globalNamespace());
// Create images
typedef QPair<QString, QString> Pair;
QList<Pair> inputOutputFiles;
inputOutputFiles.append(qMakePair(QString(fileName + QLatin1String(".ast.dot")),
QString(fileName + QLatin1String(".ast.png"))));
inputOutputFiles.append(qMakePair(QString(fileName + QLatin1String(".symbols.dot")),
QString(fileName + QLatin1String(".symbols.png"))));
foreach (const Pair &pair, inputOutputFiles) {
createImageFromDot(pair.first, pair.second, optionVerbose);
std::cout << qPrintable(QDir::toNativeSeparators(pair.second)) << std::endl;
}
}
return EXIT_SUCCESS;

View File

@@ -0,0 +1,12 @@
QT = core gui
macx:CONFIG -= app_bundle
win32:CONFIG += console
TEMPLATE = app
TARGET = cplusplus-ast2png
DESTDIR = ./
include(../../../qtcreator.pri)
include(../../../src/libs/cplusplus/cplusplus-lib.pri)
include(../../../src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri)
SOURCES += cplusplus-ast2png.cpp

View File

@@ -1,5 +0,0 @@
#!/bin/sh
me=$(dirname $0)
${CPP-gcc} -U__BLOCKS__ -xc++ -E -include $me/conf.c++ $* > $me/file.i
$me/cplusplus0 $me/file.i

View File

@@ -1,15 +0,0 @@
#define __extension__
#define __context__
#define __range__
#define __asm(a...)
#define __asm__(a...)
#define restrict
#define __restrict
#define __restrict__
// #define __weak
#define __builtin_va_arg(a,b) ((b)0)
#define __stdcall
#define __fastcall
#define __imag__
#define __real__
#define __complex__

View File

@@ -1,20 +0,0 @@
QT = core gui
macx:CONFIG -= app_bundle
TARGET = cplusplus0
include(../../../qtcreator.pri)
include(../../../src/libs/cplusplus/cplusplus.pri)
# Input
SOURCES += main.cpp
unix {
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
RCC_DIR = $${OUT_PWD}/.rcc/
UI_DIR = $${OUT_PWD}/.uic/
}

View File

@@ -1,5 +1,5 @@
TEMPLATE=subdirs
SUBDIRS= \
cplusplus-dump \
cplusplus-ast2png \
qml-ast2dot