forked from qt-creator/qt-creator
Some cleanup in CppPreprocessor.
This commit is contained in:
@@ -31,7 +31,6 @@
|
|||||||
**
|
**
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#define _SCL_SECURE_NO_WARNINGS 1
|
|
||||||
#include "pp.h"
|
#include "pp.h"
|
||||||
|
|
||||||
#include "cppmodelmanager.h"
|
#include "cppmodelmanager.h"
|
||||||
@@ -70,11 +69,10 @@
|
|||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
using namespace CppTools;
|
||||||
|
using namespace CppTools::Internal;
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
namespace CppTools {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
static const char pp_configuration_file[] = "<configuration>";
|
static const char pp_configuration_file[] = "<configuration>";
|
||||||
|
|
||||||
static const char pp_configuration[] =
|
static const char pp_configuration[] =
|
||||||
@@ -106,278 +104,40 @@ static const char pp_configuration[] =
|
|||||||
"#define __declspec(a)\n"
|
"#define __declspec(a)\n"
|
||||||
"#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method\n";
|
"#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method\n";
|
||||||
|
|
||||||
|
namespace CppTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
class CppPreprocessor: public rpp::Client
|
class CppPreprocessor: public rpp::Client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CppPreprocessor(QPointer<CppModelManager> modelManager)
|
CppPreprocessor(QPointer<CppModelManager> modelManager);
|
||||||
: m_modelManager(modelManager),
|
|
||||||
m_documents(modelManager->documents()),
|
|
||||||
m_proc(this, env)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void setWorkingCopy(const QMap<QString, QByteArray> &workingCopy)
|
void setWorkingCopy(const QMap<QString, QByteArray> &workingCopy);
|
||||||
{ m_workingCopy = workingCopy; }
|
void setIncludePaths(const QStringList &includePaths);
|
||||||
|
void setFrameworkPaths(const QStringList &frameworkPaths);
|
||||||
void setIncludePaths(const QStringList &includePaths)
|
void addIncludePath(const QString &path);
|
||||||
{ m_includePaths = includePaths; }
|
void setProjectFiles(const QStringList &files);
|
||||||
|
void run(QString &fileName);
|
||||||
void setFrameworkPaths(const QStringList &frameworkPaths)
|
void operator()(QString &fileName);
|
||||||
{ m_frameworkPaths = frameworkPaths; }
|
|
||||||
|
|
||||||
void addIncludePath(const QString &path)
|
|
||||||
{ m_includePaths.append(path); }
|
|
||||||
|
|
||||||
void setProjectFiles(const QStringList &files)
|
|
||||||
{ m_projectFiles = files; }
|
|
||||||
|
|
||||||
void run(QString &fileName)
|
|
||||||
{ sourceNeeded(fileName, IncludeGlobal); }
|
|
||||||
|
|
||||||
void operator()(QString &fileName)
|
|
||||||
{ run(fileName); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool includeFile(const QString &absoluteFilePath, QByteArray *result)
|
CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc);
|
||||||
{
|
|
||||||
if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_workingCopy.contains(absoluteFilePath)) {
|
bool includeFile(const QString &absoluteFilePath, QByteArray *result);
|
||||||
m_included.insert(absoluteFilePath);
|
QByteArray tryIncludeFile(QString &fileName, IncludeType type);
|
||||||
*result = m_workingCopy.value(absoluteFilePath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFileInfo fileInfo(absoluteFilePath);
|
void mergeEnvironment(CPlusPlus::Document::Ptr doc);
|
||||||
if (! fileInfo.isFile())
|
void mergeEnvironment(CPlusPlus::Document::Ptr doc, QSet<QString> *processed);
|
||||||
return false;
|
|
||||||
|
|
||||||
QFile file(absoluteFilePath);
|
|
||||||
if (file.open(QFile::ReadOnly)) {
|
|
||||||
m_included.insert(absoluteFilePath);
|
|
||||||
QTextStream stream(&file);
|
|
||||||
const QString contents = stream.readAll();
|
|
||||||
*result = contents.toUtf8();
|
|
||||||
file.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray tryIncludeFile(QString &fileName, IncludeType type)
|
|
||||||
{
|
|
||||||
QFileInfo fileInfo(fileName);
|
|
||||||
if (fileName == QLatin1String(pp_configuration_file) || fileInfo.isAbsolute()) {
|
|
||||||
QByteArray contents;
|
|
||||||
includeFile(fileName, &contents);
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == IncludeLocal && m_currentDoc) {
|
|
||||||
QFileInfo currentFileInfo(m_currentDoc->fileName());
|
|
||||||
QString path = currentFileInfo.absolutePath();
|
|
||||||
path += QLatin1Char('/');
|
|
||||||
path += fileName;
|
|
||||||
path = QDir::cleanPath(path);
|
|
||||||
QByteArray contents;
|
|
||||||
if (includeFile(path, &contents)) {
|
|
||||||
fileName = path;
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const QString &includePath, m_includePaths) {
|
|
||||||
QString path = includePath;
|
|
||||||
path += QLatin1Char('/');
|
|
||||||
path += fileName;
|
|
||||||
path = QDir::cleanPath(path);
|
|
||||||
QByteArray contents;
|
|
||||||
if (includeFile(path, &contents)) {
|
|
||||||
fileName = path;
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// look in the system include paths
|
|
||||||
foreach (const QString &includePath, m_systemIncludePaths) {
|
|
||||||
QString path = includePath;
|
|
||||||
path += QLatin1Char('/');
|
|
||||||
path += fileName;
|
|
||||||
path = QDir::cleanPath(path);
|
|
||||||
QByteArray contents;
|
|
||||||
if (includeFile(path, &contents)) {
|
|
||||||
fileName = path;
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = fileName.indexOf(QLatin1Char('/'));
|
|
||||||
if (index != -1) {
|
|
||||||
QString frameworkName = fileName.left(index);
|
|
||||||
QString name = fileName.mid(index + 1);
|
|
||||||
|
|
||||||
foreach (const QString &frameworkPath, m_frameworkPaths) {
|
|
||||||
QString path = frameworkPath;
|
|
||||||
path += QLatin1Char('/');
|
|
||||||
path += frameworkName;
|
|
||||||
path += QLatin1String(".framework/Headers/");
|
|
||||||
path += name;
|
|
||||||
QByteArray contents;
|
|
||||||
if (includeFile(path, &contents)) {
|
|
||||||
fileName = path;
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString path = fileName;
|
|
||||||
if (path.at(0) != QLatin1Char('/'))
|
|
||||||
path.prepend(QLatin1Char('/'));
|
|
||||||
|
|
||||||
foreach (const QString &projectFile, m_projectFiles) {
|
|
||||||
if (projectFile.endsWith(path)) {
|
|
||||||
fileName = projectFile;
|
|
||||||
QByteArray contents;
|
|
||||||
includeFile(fileName, &contents);
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//qDebug() << "**** file" << fileName << "not found!";
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void macroAdded(const QByteArray ¯oName, const QByteArray ¯oText)
|
|
||||||
{
|
|
||||||
if (! m_currentDoc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_currentDoc->appendMacro(macroName, macroText);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
virtual void macroAdded(const QByteArray ¯oName,
|
||||||
|
const QByteArray ¯oText);
|
||||||
virtual void startExpandingMacro(unsigned offset,
|
virtual void startExpandingMacro(unsigned offset,
|
||||||
const rpp::Macro &,
|
const rpp::Macro ¯o,
|
||||||
const QByteArray &originalText)
|
const QByteArray &originalText);
|
||||||
{
|
virtual void stopExpandingMacro(unsigned offset, const rpp::Macro ¯o);
|
||||||
if (! m_currentDoc)
|
virtual void startSkippingBlocks(unsigned offset);
|
||||||
return;
|
virtual void stopSkippingBlocks(unsigned offset);
|
||||||
|
virtual void sourceNeeded(QString &fileName, IncludeType type);
|
||||||
//qDebug() << "start expanding:" << macro.name << "text:" << originalText;
|
|
||||||
m_currentDoc->addMacroUse(offset, originalText.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void stopExpandingMacro(unsigned, const rpp::Macro &)
|
|
||||||
{
|
|
||||||
if (! m_currentDoc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//qDebug() << "stop expanding:" << macro.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mergeEnvironment(Document::Ptr doc)
|
|
||||||
{
|
|
||||||
QSet<QString> processed;
|
|
||||||
mergeEnvironment(doc, &processed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mergeEnvironment(Document::Ptr doc, QSet<QString> *processed)
|
|
||||||
{
|
|
||||||
if (! doc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const QString fn = doc->fileName();
|
|
||||||
|
|
||||||
if (processed->contains(fn))
|
|
||||||
return;
|
|
||||||
|
|
||||||
processed->insert(fn);
|
|
||||||
|
|
||||||
foreach (QString includedFile, doc->includedFiles())
|
|
||||||
mergeEnvironment(m_documents.value(includedFile), processed);
|
|
||||||
|
|
||||||
const QByteArray macros = doc->definedMacros();
|
|
||||||
QByteArray localFileName = doc->fileName().toUtf8();
|
|
||||||
|
|
||||||
QByteArray dummy;
|
|
||||||
m_proc(localFileName, macros, &dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void startSkippingBlocks(unsigned offset)
|
|
||||||
{
|
|
||||||
//qDebug() << "start skipping blocks:" << offset;
|
|
||||||
if (m_currentDoc)
|
|
||||||
m_currentDoc->startSkippingBlocks(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void stopSkippingBlocks(unsigned offset)
|
|
||||||
{
|
|
||||||
//qDebug() << "stop skipping blocks:" << offset;
|
|
||||||
if (m_currentDoc)
|
|
||||||
m_currentDoc->stopSkippingBlocks(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void sourceNeeded(QString &fileName, IncludeType type)
|
|
||||||
{
|
|
||||||
if (fileName.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QByteArray contents = tryIncludeFile(fileName, type);
|
|
||||||
|
|
||||||
if (m_currentDoc) {
|
|
||||||
m_currentDoc->addIncludeFile(fileName);
|
|
||||||
if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) {
|
|
||||||
QString msg;
|
|
||||||
msg += fileName;
|
|
||||||
msg += QLatin1String(": No such file or directory");
|
|
||||||
Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
|
|
||||||
m_currentDoc->fileName(),
|
|
||||||
env.currentLine, /*column = */ 0,
|
|
||||||
msg);
|
|
||||||
m_currentDoc->addDiagnosticMessage(d);
|
|
||||||
//qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! contents.isEmpty()) {
|
|
||||||
Document::Ptr cachedDoc = m_documents.value(fileName);
|
|
||||||
if (cachedDoc && m_currentDoc) {
|
|
||||||
mergeEnvironment(cachedDoc);
|
|
||||||
} else {
|
|
||||||
Document::Ptr previousDoc = switchDocument(Document::create(fileName));
|
|
||||||
|
|
||||||
const QByteArray previousFile = env.current_file;
|
|
||||||
const unsigned previousLine = env.currentLine;
|
|
||||||
|
|
||||||
env.current_file = QByteArray(m_currentDoc->translationUnit()->fileName(),
|
|
||||||
m_currentDoc->translationUnit()->fileNameLength());
|
|
||||||
|
|
||||||
QByteArray preprocessedCode;
|
|
||||||
m_proc(contents, &preprocessedCode);
|
|
||||||
//qDebug() << preprocessedCode;
|
|
||||||
|
|
||||||
env.current_file = previousFile;
|
|
||||||
env.currentLine = previousLine;
|
|
||||||
|
|
||||||
m_currentDoc->setSource(preprocessedCode);
|
|
||||||
m_currentDoc->parse();
|
|
||||||
m_currentDoc->check();
|
|
||||||
m_currentDoc->releaseTranslationUnit(); // release the AST and the token stream.
|
|
||||||
|
|
||||||
if (m_modelManager)
|
|
||||||
m_modelManager->emitDocumentUpdated(m_currentDoc);
|
|
||||||
(void) switchDocument(previousDoc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Document::Ptr switchDocument(Document::Ptr doc)
|
|
||||||
{
|
|
||||||
Document::Ptr previousDoc = m_currentDoc;
|
|
||||||
m_currentDoc = doc;
|
|
||||||
return previousDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<CppModelManager> m_modelManager;
|
QPointer<CppModelManager> m_modelManager;
|
||||||
@@ -390,15 +150,282 @@ private:
|
|||||||
QStringList m_projectFiles;
|
QStringList m_projectFiles;
|
||||||
QStringList m_frameworkPaths;
|
QStringList m_frameworkPaths;
|
||||||
QSet<QString> m_included;
|
QSet<QString> m_included;
|
||||||
Document::Ptr m_currentDoc;
|
CPlusPlus::Document::Ptr m_currentDoc;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|
||||||
|
CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager)
|
||||||
|
: m_modelManager(modelManager),
|
||||||
|
m_documents(modelManager->documents()),
|
||||||
|
m_proc(this, env)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void CppPreprocessor::setWorkingCopy(const QMap<QString, QByteArray> &workingCopy)
|
||||||
|
{ m_workingCopy = workingCopy; }
|
||||||
|
|
||||||
|
void CppPreprocessor::setIncludePaths(const QStringList &includePaths)
|
||||||
|
{ m_includePaths = includePaths; }
|
||||||
|
|
||||||
|
void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths)
|
||||||
|
{ m_frameworkPaths = frameworkPaths; }
|
||||||
|
|
||||||
|
void CppPreprocessor::addIncludePath(const QString &path)
|
||||||
|
{ m_includePaths.append(path); }
|
||||||
|
|
||||||
|
void CppPreprocessor::setProjectFiles(const QStringList &files)
|
||||||
|
{ m_projectFiles = files; }
|
||||||
|
|
||||||
|
void CppPreprocessor::run(QString &fileName)
|
||||||
|
{ sourceNeeded(fileName, IncludeGlobal); }
|
||||||
|
|
||||||
|
void CppPreprocessor::operator()(QString &fileName)
|
||||||
|
{ run(fileName); }
|
||||||
|
|
||||||
|
bool CppPreprocessor::includeFile(const QString &absoluteFilePath, QByteArray *result)
|
||||||
|
{
|
||||||
|
if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_workingCopy.contains(absoluteFilePath)) {
|
||||||
|
m_included.insert(absoluteFilePath);
|
||||||
|
*result = m_workingCopy.value(absoluteFilePath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo fileInfo(absoluteFilePath);
|
||||||
|
if (! fileInfo.isFile())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QFile file(absoluteFilePath);
|
||||||
|
if (file.open(QFile::ReadOnly)) {
|
||||||
|
m_included.insert(absoluteFilePath);
|
||||||
|
QTextStream stream(&file);
|
||||||
|
const QString contents = stream.readAll();
|
||||||
|
*result = contents.toUtf8();
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray CppPreprocessor::tryIncludeFile(QString &fileName, IncludeType type)
|
||||||
|
{
|
||||||
|
QFileInfo fileInfo(fileName);
|
||||||
|
if (fileName == QLatin1String(pp_configuration_file) || fileInfo.isAbsolute()) {
|
||||||
|
QByteArray contents;
|
||||||
|
includeFile(fileName, &contents);
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == IncludeLocal && m_currentDoc) {
|
||||||
|
QFileInfo currentFileInfo(m_currentDoc->fileName());
|
||||||
|
QString path = currentFileInfo.absolutePath();
|
||||||
|
path += QLatin1Char('/');
|
||||||
|
path += fileName;
|
||||||
|
path = QDir::cleanPath(path);
|
||||||
|
QByteArray contents;
|
||||||
|
if (includeFile(path, &contents)) {
|
||||||
|
fileName = path;
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QString &includePath, m_includePaths) {
|
||||||
|
QString path = includePath;
|
||||||
|
path += QLatin1Char('/');
|
||||||
|
path += fileName;
|
||||||
|
path = QDir::cleanPath(path);
|
||||||
|
QByteArray contents;
|
||||||
|
if (includeFile(path, &contents)) {
|
||||||
|
fileName = path;
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// look in the system include paths
|
||||||
|
foreach (const QString &includePath, m_systemIncludePaths) {
|
||||||
|
QString path = includePath;
|
||||||
|
path += QLatin1Char('/');
|
||||||
|
path += fileName;
|
||||||
|
path = QDir::cleanPath(path);
|
||||||
|
QByteArray contents;
|
||||||
|
if (includeFile(path, &contents)) {
|
||||||
|
fileName = path;
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = fileName.indexOf(QLatin1Char('/'));
|
||||||
|
if (index != -1) {
|
||||||
|
QString frameworkName = fileName.left(index);
|
||||||
|
QString name = fileName.mid(index + 1);
|
||||||
|
|
||||||
|
foreach (const QString &frameworkPath, m_frameworkPaths) {
|
||||||
|
QString path = frameworkPath;
|
||||||
|
path += QLatin1Char('/');
|
||||||
|
path += frameworkName;
|
||||||
|
path += QLatin1String(".framework/Headers/");
|
||||||
|
path += name;
|
||||||
|
QByteArray contents;
|
||||||
|
if (includeFile(path, &contents)) {
|
||||||
|
fileName = path;
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString path = fileName;
|
||||||
|
if (path.at(0) != QLatin1Char('/'))
|
||||||
|
path.prepend(QLatin1Char('/'));
|
||||||
|
|
||||||
|
foreach (const QString &projectFile, m_projectFiles) {
|
||||||
|
if (projectFile.endsWith(path)) {
|
||||||
|
fileName = projectFile;
|
||||||
|
QByteArray contents;
|
||||||
|
includeFile(fileName, &contents);
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//qDebug() << "**** file" << fileName << "not found!";
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::macroAdded(const QByteArray ¯oName, const QByteArray ¯oText)
|
||||||
|
{
|
||||||
|
if (! m_currentDoc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_currentDoc->appendMacro(macroName, macroText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::startExpandingMacro(unsigned offset,
|
||||||
|
const rpp::Macro &,
|
||||||
|
const QByteArray &originalText)
|
||||||
|
{
|
||||||
|
if (! m_currentDoc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//qDebug() << "start expanding:" << macro.name << "text:" << originalText;
|
||||||
|
m_currentDoc->addMacroUse(offset, originalText.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::stopExpandingMacro(unsigned, const rpp::Macro &)
|
||||||
|
{
|
||||||
|
if (! m_currentDoc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//qDebug() << "stop expanding:" << macro.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::mergeEnvironment(Document::Ptr doc)
|
||||||
|
{
|
||||||
|
QSet<QString> processed;
|
||||||
|
mergeEnvironment(doc, &processed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::mergeEnvironment(Document::Ptr doc, QSet<QString> *processed)
|
||||||
|
{
|
||||||
|
if (! doc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QString fn = doc->fileName();
|
||||||
|
|
||||||
|
if (processed->contains(fn))
|
||||||
|
return;
|
||||||
|
|
||||||
|
processed->insert(fn);
|
||||||
|
|
||||||
|
foreach (QString includedFile, doc->includedFiles())
|
||||||
|
mergeEnvironment(m_documents.value(includedFile), processed);
|
||||||
|
|
||||||
|
const QByteArray macros = doc->definedMacros();
|
||||||
|
QByteArray localFileName = doc->fileName().toUtf8();
|
||||||
|
|
||||||
|
QByteArray dummy;
|
||||||
|
m_proc(localFileName, macros, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::startSkippingBlocks(unsigned offset)
|
||||||
|
{
|
||||||
|
//qDebug() << "start skipping blocks:" << offset;
|
||||||
|
if (m_currentDoc)
|
||||||
|
m_currentDoc->startSkippingBlocks(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::stopSkippingBlocks(unsigned offset)
|
||||||
|
{
|
||||||
|
//qDebug() << "stop skipping blocks:" << offset;
|
||||||
|
if (m_currentDoc)
|
||||||
|
m_currentDoc->stopSkippingBlocks(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type)
|
||||||
|
{
|
||||||
|
if (fileName.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QByteArray contents = tryIncludeFile(fileName, type);
|
||||||
|
|
||||||
|
if (m_currentDoc) {
|
||||||
|
m_currentDoc->addIncludeFile(fileName);
|
||||||
|
if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) {
|
||||||
|
QString msg;
|
||||||
|
msg += fileName;
|
||||||
|
msg += QLatin1String(": No such file or directory");
|
||||||
|
Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
|
||||||
|
m_currentDoc->fileName(),
|
||||||
|
env.currentLine, /*column = */ 0,
|
||||||
|
msg);
|
||||||
|
m_currentDoc->addDiagnosticMessage(d);
|
||||||
|
//qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! contents.isEmpty()) {
|
||||||
|
Document::Ptr cachedDoc = m_documents.value(fileName);
|
||||||
|
if (cachedDoc && m_currentDoc) {
|
||||||
|
mergeEnvironment(cachedDoc);
|
||||||
|
} else {
|
||||||
|
Document::Ptr previousDoc = switchDocument(Document::create(fileName));
|
||||||
|
|
||||||
|
const QByteArray previousFile = env.current_file;
|
||||||
|
const unsigned previousLine = env.currentLine;
|
||||||
|
|
||||||
|
env.current_file = QByteArray(m_currentDoc->translationUnit()->fileName(),
|
||||||
|
m_currentDoc->translationUnit()->fileNameLength());
|
||||||
|
|
||||||
|
QByteArray preprocessedCode;
|
||||||
|
m_proc(contents, &preprocessedCode);
|
||||||
|
//qDebug() << preprocessedCode;
|
||||||
|
|
||||||
|
env.current_file = previousFile;
|
||||||
|
env.currentLine = previousLine;
|
||||||
|
|
||||||
|
m_currentDoc->setSource(preprocessedCode);
|
||||||
|
m_currentDoc->parse();
|
||||||
|
m_currentDoc->check();
|
||||||
|
m_currentDoc->releaseTranslationUnit(); // release the AST and the token stream.
|
||||||
|
|
||||||
|
if (m_modelManager)
|
||||||
|
m_modelManager->emitDocumentUpdated(m_currentDoc);
|
||||||
|
(void) switchDocument(previousDoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
|
||||||
|
{
|
||||||
|
Document::Ptr previousDoc = m_currentDoc;
|
||||||
|
m_currentDoc = doc;
|
||||||
|
return previousDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
using namespace CppTools;
|
|
||||||
using namespace CppTools::Internal;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class CppTools::CppModelManager
|
\class CppTools::CppModelManager
|
||||||
|
|||||||
Reference in New Issue
Block a user