forked from qt-creator/qt-creator
Added AST forward declaration generation.
Done with Erik Verbruggen
This commit is contained in:
@@ -22,6 +22,34 @@
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
QTextCursor createCursor(TranslationUnit *unit, AST *ast, QTextDocument *document)
|
||||
{
|
||||
unsigned startLine, startColumn, endLine, endColumn;
|
||||
unit->getTokenStartPosition(ast->firstToken(), &startLine, &startColumn);
|
||||
unit->getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn);
|
||||
|
||||
QTextCursor tc(document);
|
||||
tc.setPosition(document->findBlockByNumber(startLine - 1).position());
|
||||
tc.setPosition(document->findBlockByNumber(endLine - 1).position() + endColumn - 1,
|
||||
QTextCursor::KeepAnchor);
|
||||
|
||||
int charsToSkip = 0;
|
||||
forever {
|
||||
QChar ch = document->characterAt(tc.position() + charsToSkip);
|
||||
|
||||
if (! ch.isSpace())
|
||||
break;
|
||||
|
||||
++charsToSkip;
|
||||
|
||||
if (ch == QChar::ParagraphSeparator)
|
||||
break;
|
||||
}
|
||||
|
||||
tc.setPosition(tc.position() + charsToSkip, QTextCursor::KeepAnchor);
|
||||
return tc;
|
||||
}
|
||||
|
||||
class ASTNodes
|
||||
{
|
||||
public:
|
||||
@@ -73,25 +101,8 @@ protected:
|
||||
|
||||
Q_ASSERT(accessDeclaration != 0);
|
||||
|
||||
unsigned endLine, endColumn;
|
||||
getTokenEndPosition(accessDeclaration->lastToken() - 1, &endLine, &endColumn);
|
||||
|
||||
QTextCursor tc(document);
|
||||
tc.setPosition(document->findBlockByNumber(endLine - 1).position() + endColumn - 1);
|
||||
|
||||
int charsToSkip = 0;
|
||||
forever {
|
||||
QChar ch = document->characterAt(tc.position() + charsToSkip);
|
||||
if (! ch.isSpace())
|
||||
break;
|
||||
|
||||
++charsToSkip;
|
||||
|
||||
if (ch == QChar::ParagraphSeparator)
|
||||
break;
|
||||
}
|
||||
|
||||
tc.setPosition(tc.position() + charsToSkip);
|
||||
QTextCursor tc = createCursor(translationUnit(), accessDeclaration, document);
|
||||
tc.setPosition(tc.position());
|
||||
|
||||
_nodes.endOfPublicClassSpecifiers.append(tc);
|
||||
}
|
||||
@@ -127,29 +138,8 @@ protected:
|
||||
|
||||
if (functionName.length() > 3 && functionName.startsWith(QLatin1String("as"))
|
||||
&& functionName.at(2).isUpper()) {
|
||||
unsigned startLine, startColumn, endLine, endColumn;
|
||||
getTokenStartPosition(ast->firstToken(), &startLine, &startColumn);
|
||||
getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn);
|
||||
|
||||
QTextCursor tc(document);
|
||||
tc.setPosition(document->findBlockByNumber(startLine - 1).position());
|
||||
tc.setPosition(document->findBlockByNumber(endLine - 1).position() + endColumn - 1,
|
||||
QTextCursor::KeepAnchor);
|
||||
|
||||
int charsToSkip = 0;
|
||||
forever {
|
||||
QChar ch = document->characterAt(tc.position() + charsToSkip);
|
||||
|
||||
if (! ch.isSpace())
|
||||
break;
|
||||
|
||||
++charsToSkip;
|
||||
|
||||
if (ch == QChar::ParagraphSeparator)
|
||||
break;
|
||||
}
|
||||
|
||||
tc.setPosition(tc.position() + charsToSkip, QTextCursor::KeepAnchor);
|
||||
QTextCursor tc = createCursor(translationUnit(), ast, document);
|
||||
|
||||
//qDebug() << qPrintable(tc.selectedText());
|
||||
_cursors.append(tc);
|
||||
@@ -164,8 +154,10 @@ private:
|
||||
Overview oo;
|
||||
};
|
||||
|
||||
void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir)
|
||||
QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir)
|
||||
{
|
||||
QStringList astDerivedClasses;
|
||||
|
||||
QFileInfo fileAST_h(cplusplusDir, QLatin1String("AST.h"));
|
||||
Q_ASSERT(fileAST_h.exists());
|
||||
|
||||
@@ -173,7 +165,7 @@ void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir)
|
||||
|
||||
QFile file(fileName);
|
||||
if (! file.open(QFile::ReadOnly))
|
||||
return;
|
||||
return astDerivedClasses;
|
||||
|
||||
const QString source = QTextStream(&file).readAll();
|
||||
file.close();
|
||||
@@ -204,6 +196,8 @@ void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir)
|
||||
const QString methodName = QLatin1String("as") + className.mid(0, className.length() - 3);
|
||||
replacementCastMethods[classAST] = QString(" virtual %1 *%2() { return this; }\n").arg(className, methodName);
|
||||
castMethods.append(QString(" virtual %1 *%2() { return 0; }\n").arg(className, methodName));
|
||||
|
||||
astDerivedClasses.append(className);
|
||||
}
|
||||
|
||||
if (! baseCastMethodCursors.isEmpty()) {
|
||||
@@ -231,6 +225,85 @@ void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir)
|
||||
QTextStream out(&file);
|
||||
out << document.toPlainText();
|
||||
}
|
||||
|
||||
return astDerivedClasses;
|
||||
}
|
||||
|
||||
class FindASTForwards: protected ASTVisitor
|
||||
{
|
||||
public:
|
||||
FindASTForwards(Document::Ptr doc, QTextDocument *document)
|
||||
: ASTVisitor(doc->control()), document(document)
|
||||
{}
|
||||
|
||||
QList<QTextCursor> operator()(AST *ast)
|
||||
{
|
||||
accept(ast);
|
||||
return _cursors;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool visit(SimpleDeclarationAST *ast)
|
||||
{
|
||||
if (ElaboratedTypeSpecifierAST *e = ast->decl_specifier_seq->asElaboratedTypeSpecifier()) {
|
||||
if (tokenKind(e->classkey_token) == T_CLASS && !ast->declarators) {
|
||||
QString className = oo(e->name->name);
|
||||
|
||||
if (className.length() > 3 && className.endsWith(QLatin1String("AST"))) {
|
||||
QTextCursor tc = createCursor(translationUnit(), ast, document);
|
||||
_cursors.append(tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
QTextDocument *document;
|
||||
QList<QTextCursor> _cursors;
|
||||
Overview oo;
|
||||
};
|
||||
|
||||
void generateASTFwd_h(const Snapshot &snapshot, const QDir &cplusplusDir, const QStringList &astDerivedClasses)
|
||||
{
|
||||
QFileInfo fileASTFwd_h(cplusplusDir, QLatin1String("ASTfwd.h"));
|
||||
Q_ASSERT(fileASTFwd_h.exists());
|
||||
|
||||
const QString fileName = fileASTFwd_h.absoluteFilePath();
|
||||
|
||||
QFile file(fileName);
|
||||
if (! file.open(QFile::ReadOnly))
|
||||
return;
|
||||
|
||||
const QString source = QTextStream(&file).readAll();
|
||||
file.close();
|
||||
|
||||
QTextDocument document;
|
||||
document.setPlainText(source);
|
||||
|
||||
Document::Ptr doc = Document::create(fileName);
|
||||
const QByteArray preprocessedCode = snapshot.preprocessedCode(source, fileName);
|
||||
doc->setSource(preprocessedCode);
|
||||
doc->check();
|
||||
|
||||
FindASTForwards process(doc, &document);
|
||||
QList<QTextCursor> cursors = process(doc->translationUnit()->ast());
|
||||
|
||||
for (int i = 0; i < cursors.length(); ++i)
|
||||
cursors[i].removeSelectedText();
|
||||
|
||||
QString replacement;
|
||||
foreach (const QString &astDerivedClass, astDerivedClasses) {
|
||||
replacement += QString(QLatin1String("class %1;\n")).arg(astDerivedClass);
|
||||
}
|
||||
|
||||
cursors.first().insertText(replacement);
|
||||
|
||||
if (file.open(QFile::WriteOnly)) {
|
||||
QTextStream out(&file);
|
||||
out << document.toPlainText();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -247,5 +320,7 @@ int main(int argc, char *argv[])
|
||||
QDir cplusplusDir(files.first());
|
||||
Snapshot snapshot;
|
||||
|
||||
generateAST_H(snapshot, cplusplusDir);
|
||||
QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir);
|
||||
astDerivedClasses.sort();
|
||||
generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user