forked from qt-creator/qt-creator
Initial import
This commit is contained in:
242
src/libs/cplusplus/CppDocument.cpp
Normal file
242
src/libs/cplusplus/CppDocument.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
|
||||
#include "CppDocument.h"
|
||||
#include <Control.h>
|
||||
#include <TranslationUnit.h>
|
||||
#include <DiagnosticClient.h>
|
||||
#include <Semantic.h>
|
||||
#include <Literals.h>
|
||||
#include <Symbols.h>
|
||||
#include <AST.h>
|
||||
#include <Scope.h>
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QtDebug>
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
namespace {
|
||||
class DocumentDiagnosticClient: public DiagnosticClient
|
||||
{
|
||||
enum { MAX_MESSAGE_COUNT = 10 };
|
||||
|
||||
public:
|
||||
DocumentDiagnosticClient(Document *doc, QList<Document::DiagnosticMessage> *messages)
|
||||
: doc(doc),
|
||||
messages(messages)
|
||||
{ }
|
||||
|
||||
virtual void report(int level,
|
||||
StringLiteral *fileId,
|
||||
unsigned line, unsigned column,
|
||||
const char *format, va_list ap)
|
||||
{
|
||||
if (messages->count() == MAX_MESSAGE_COUNT)
|
||||
return;
|
||||
|
||||
const QString fileName = QString::fromUtf8(fileId->chars(), fileId->size());
|
||||
|
||||
if (fileName != doc->fileName())
|
||||
return;
|
||||
|
||||
QString message;
|
||||
message.vsprintf(format, ap);
|
||||
|
||||
Document::DiagnosticMessage m(convertLevel(level), doc->fileName(),
|
||||
line, column, message);
|
||||
messages->append(m);
|
||||
}
|
||||
|
||||
static int convertLevel(int level) {
|
||||
switch (level) {
|
||||
case Warning: return Document::DiagnosticMessage::Warning;
|
||||
case Error: return Document::DiagnosticMessage::Error;
|
||||
case Fatal: return Document::DiagnosticMessage::Fatal;
|
||||
default: return Document::DiagnosticMessage::Error;
|
||||
}
|
||||
}
|
||||
|
||||
Document *doc;
|
||||
QList<Document::DiagnosticMessage> *messages;
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
Document::Document(const QString &fileName)
|
||||
: _fileName(fileName),
|
||||
_globalNamespace(0)
|
||||
{
|
||||
_control = new Control();
|
||||
|
||||
_control->setDiagnosticClient(new DocumentDiagnosticClient(this, &_diagnosticMessages));
|
||||
|
||||
const QByteArray localFileName = fileName.toUtf8();
|
||||
StringLiteral *fileId = _control->findOrInsertFileName(localFileName.constData(),
|
||||
localFileName.size());
|
||||
_translationUnit = new TranslationUnit(_control, fileId);
|
||||
_translationUnit->setQtMocRunEnabled(true);
|
||||
(void) _control->switchTranslationUnit(_translationUnit);
|
||||
}
|
||||
|
||||
Document::~Document()
|
||||
{
|
||||
delete _translationUnit;
|
||||
delete _control->diagnosticClient();
|
||||
delete _control;
|
||||
}
|
||||
|
||||
Control *Document::control() const
|
||||
{ return _control; }
|
||||
|
||||
QString Document::fileName() const
|
||||
{ return _fileName; }
|
||||
|
||||
QStringList Document::includedFiles() const
|
||||
{ return _includedFiles; }
|
||||
|
||||
void Document::addIncludeFile(const QString &fileName)
|
||||
{ _includedFiles.append(fileName); }
|
||||
|
||||
QByteArray Document::definedMacros() const
|
||||
{ return _definedMacros; }
|
||||
|
||||
void Document::appendMacro(const QByteArray ¯oName, const QByteArray &text)
|
||||
{
|
||||
int index = macroName.indexOf('(');
|
||||
if (index == -1)
|
||||
_macroNames.insert(macroName);
|
||||
else
|
||||
_macroNames.insert(macroName.left(index));
|
||||
_definedMacros += text;
|
||||
}
|
||||
|
||||
TranslationUnit *Document::translationUnit() const
|
||||
{ return _translationUnit; }
|
||||
|
||||
bool Document::skipFunctionBody() const
|
||||
{ return _translationUnit->skipFunctionBody(); }
|
||||
|
||||
void Document::setSkipFunctionBody(bool skipFunctionBody)
|
||||
{ _translationUnit->setSkipFunctionBody(skipFunctionBody); }
|
||||
|
||||
unsigned Document::globalSymbolCount() const
|
||||
{
|
||||
if (! _globalNamespace)
|
||||
return 0;
|
||||
|
||||
return _globalNamespace->memberCount();
|
||||
}
|
||||
|
||||
Symbol *Document::globalSymbolAt(unsigned index) const
|
||||
{ return _globalNamespace->memberAt(index); }
|
||||
|
||||
Scope *Document::globalSymbols() const
|
||||
{
|
||||
if (! _globalNamespace)
|
||||
return 0;
|
||||
|
||||
return _globalNamespace->members();
|
||||
}
|
||||
|
||||
Namespace *Document::globalNamespace() const
|
||||
{ return _globalNamespace; }
|
||||
|
||||
Symbol *Document::findSymbolAt(unsigned line, unsigned column) const
|
||||
{ return findSymbolAt(line, column, globalSymbols()); }
|
||||
|
||||
Symbol *Document::findSymbolAt(unsigned line, unsigned column, Scope *scope) const
|
||||
{
|
||||
Symbol *previousSymbol = 0;
|
||||
|
||||
for (unsigned i = 0; i < scope->symbolCount(); ++i) {
|
||||
Symbol *symbol = scope->symbolAt(i);
|
||||
if (symbol->line() > line)
|
||||
break;
|
||||
|
||||
previousSymbol = symbol;
|
||||
}
|
||||
|
||||
if (previousSymbol) {
|
||||
if (ScopedSymbol *scoped = previousSymbol->asScopedSymbol()) {
|
||||
if (Symbol *member = findSymbolAt(line, column, scoped->members()))
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
return previousSymbol;
|
||||
}
|
||||
|
||||
Document::Ptr Document::create(const QString &fileName)
|
||||
{
|
||||
Document::Ptr doc(new Document(fileName));
|
||||
return doc;
|
||||
}
|
||||
|
||||
void Document::setSource(const QByteArray &source)
|
||||
{ _translationUnit->setSource(source.constBegin(), source.size()); }
|
||||
|
||||
void Document::startSkippingBlocks(unsigned start)
|
||||
{ _skippedBlocks.append(Block(start, 0)); }
|
||||
|
||||
void Document::stopSkippingBlocks(unsigned stop)
|
||||
{
|
||||
unsigned start = _skippedBlocks.back().begin();
|
||||
if (start > stop)
|
||||
_skippedBlocks.removeLast(); // Ignore this block, it's invalid.
|
||||
else
|
||||
_skippedBlocks.back() = Block(start, stop);
|
||||
}
|
||||
|
||||
QSet<QByteArray> Document::macroNames() const
|
||||
{ return _macroNames; }
|
||||
|
||||
void Document::parse()
|
||||
{ _translationUnit->parse(); }
|
||||
|
||||
void Document::check()
|
||||
{
|
||||
Q_ASSERT(! _globalNamespace);
|
||||
|
||||
Semantic semantic(_control);
|
||||
|
||||
_globalNamespace = _control->newNamespace(0);
|
||||
Scope *globals = _globalNamespace->members();
|
||||
if (TranslationUnitAST *ast = _translationUnit->ast()) {
|
||||
for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) {
|
||||
semantic.check(decl, globals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Document::releaseTranslationUnit()
|
||||
{ _translationUnit->release(); }
|
Reference in New Issue
Block a user