Commit 51039b3c authored by con's avatar con
Browse files

Merge branch 'master' of scm.dev.nokia.troll.no:creator/mainline

parents 6503099b 27578a6c
......@@ -703,25 +703,17 @@ public:
};
} // end of anonymous namespace
Symbol *Snapshot::findMatchingDefinition(Symbol *symbol) const
Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
{
if (! symbol->identifier())
if (! (declaration && declaration->identifier()))
return 0;
Document::Ptr thisDocument = document(QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()));
Document::Ptr thisDocument = document(QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()));
if (! thisDocument) {
qWarning() << "undefined document:" << symbol->fileName();
qWarning() << "undefined document:" << declaration->fileName();
return 0;
}
LookupContext thisContext(thisDocument, *this);
const QList<Symbol *> declarationCandidates = thisContext.lookup(symbol->name(), symbol->scope());
if (declarationCandidates.isEmpty()) {
qWarning() << "unresolved declaration:" << symbol->fileName() << symbol->line() << symbol->column();
return 0;
}
Symbol *declaration = declarationCandidates.first();
Function *declarationTy = declaration->type()->asFunctionType();
if (! declarationTy) {
qWarning() << "not a function:" << declaration->fileName() << declaration->line() << declaration->column();
......
......@@ -58,6 +58,7 @@
#include <cpptools/cppmodelmanagerinterface.h>
#include <cpptools/cpptoolsconstants.h>
#include <cpptools/cppcodeformatter.h>
#include <coreplugin/icore.h>
#include <coreplugin/actionmanager/actionmanager.h>
......@@ -1238,7 +1239,20 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
const QList<LookupItem> resolvedSymbols = typeOfExpression(expression, scope, TypeOfExpression::Preprocess);
if (!resolvedSymbols.isEmpty()) {
const LookupItem result = skipForwardDeclarations(resolvedSymbols);
LookupItem result = skipForwardDeclarations(resolvedSymbols);
foreach (const LookupItem &r, resolvedSymbols) {
if (Symbol *d = r.declaration()) {
if (d->isDeclaration() || d->isFunction()) {
if (file()->fileName() == QString::fromUtf8(d->fileName(), d->fileNameLength())) {
if (unsigned(line) == d->line() && unsigned(column) >= d->column()) { // ### TODO: check the end
result = r; // take the symbol under cursor.
break;
}
}
}
}
}
if (Symbol *symbol = result.declaration()) {
Symbol *def = 0;
......@@ -1414,90 +1428,35 @@ bool CPPEditor::isInComment(const QTextCursor &cursor) const
return false;
}
// Indent a code line based on previous
static void indentCPPBlock(const CPPEditor::TabSettings &ts,
const QTextBlock &block,
const TextEditor::TextBlockIterator &programBegin,
const TextEditor::TextBlockIterator &programEnd,
QChar typedChar)
{
typedef SharedTools::Indenter Indenter;
Indenter &indenter = Indenter::instance();
indenter.setIndentSize(ts.m_indentSize);
indenter.setTabSize(ts.m_tabSize);
indenter.setIndentBraces(ts.m_indentBraces);
indenter.setDoubleIndentBlocks(ts.m_doubleIndentBlocks);
const TextEditor::TextBlockIterator current(block);
const int indent = indenter.indentForBottomLine(current, programBegin, programEnd, typedChar);
ts.indentLine(block, indent);
}
static int indentationColumn(const TextEditor::TabSettings &tabSettings,
const BackwardsScanner &scanner,
int index)
{
return tabSettings.indentationColumn(scanner.indentationString(index));
}
void CPPEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
{
QTextCursor tc(block);
tc.movePosition(QTextCursor::EndOfBlock);
Q_UNUSED(doc)
Q_UNUSED(typedChar)
const TabSettings &ts = tabSettings();
BackwardsScanner tk(tc, 400);
const int tokenCount = tk.startToken();
if (tokenCount != 0) {
const Token firstToken = tk[0];
if (firstToken.is(T_COLON)) {
const int previousLineIndent = indentationColumn(ts, tk, -1);
ts.indentLine(block, previousLineIndent + ts.m_indentSize);
return;
} else if ((firstToken.is(T_PUBLIC) || firstToken.is(T_PROTECTED) || firstToken.is(T_PRIVATE) ||
firstToken.is(T_Q_SIGNALS) || firstToken.is(T_Q_SLOTS)) &&
tk.size() > 1 && tk[1].is(T_COLON)) {
const int startOfBlock = tk.startOfBlock(0);
if (startOfBlock != 0) {
const int indent = indentationColumn(ts, tk, startOfBlock);
ts.indentLine(block, indent);
return;
}
} else if (firstToken.is(T_CASE) || firstToken.is(T_DEFAULT)) {
const int startOfBlock = tk.startOfBlock(0);
if (startOfBlock != 0) {
const int indent = indentationColumn(ts, tk, startOfBlock);
ts.indentLine(block, indent);
return;
}
return;
}
}
if ((tokenCount == 0 || tk[0].isNot(T_POUND)) && typedChar.isNull() && (tk[-1].is(T_IDENTIFIER) || tk[-1].is(T_RPAREN))) {
int tokenIndex = -1;
if (tk[-1].is(T_RPAREN)) {
const int matchingBrace = tk.startOfMatchingBrace(0);
if (matchingBrace != 0 && tk[matchingBrace - 1].is(T_IDENTIFIER)) {
tokenIndex = matchingBrace - 1;
}
}
const QString spell = tk.text(tokenIndex);
if (tk[tokenIndex].newline() && (spell.startsWith(QLatin1String("QT_")) ||
spell.startsWith(QLatin1String("Q_")))) {
const int indent = indentationColumn(ts, tk, tokenIndex);
ts.indentLine(block, indent);
return;
}
}
const TextEditor::TextBlockIterator begin(doc->begin());
const TextEditor::TextBlockIterator end(block.next());
indentCPPBlock(ts, block, begin, end, typedChar);
CppTools::QtStyleCodeFormatter codeFormatter;
codeFormatter.setIndentSize(ts.m_indentSize);
codeFormatter.setTabSize(ts.m_tabSize);
if (ts.m_indentBraces && ts.m_doubleIndentBlocks) { // gnu style
codeFormatter.setIndentSubstatementBraces(true);
codeFormatter.setIndentSubstatementStatements(true);
codeFormatter.setIndentDeclarationBraces(false);
codeFormatter.setIndentDeclarationMembers(true);
} else if (ts.m_indentBraces) { // whitesmiths style
codeFormatter.setIndentSubstatementBraces(true);
codeFormatter.setIndentSubstatementStatements(false);
codeFormatter.setIndentDeclarationBraces(true);
codeFormatter.setIndentDeclarationMembers(false);
} else { // default Qt style
codeFormatter.setIndentSubstatementBraces(false);
codeFormatter.setIndentSubstatementStatements(true);
codeFormatter.setIndentDeclarationBraces(false);
codeFormatter.setIndentDeclarationMembers(true);
}
const int depth = codeFormatter.indentFor(block);
ts.indentLine(block, depth);
}
bool CPPEditor::event(QEvent *e)
......@@ -1713,6 +1672,13 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
m_occurrenceRenameFormat.clearForeground();
}
void CPPEditor::setTabSettings(const TextEditor::TabSettings &ts)
{
CppTools::CodeFormatter::invalidateCache(document());
TextEditor::BaseTextEditor::setTabSettings(ts);
}
void CPPEditor::unCommentSelection()
{
Utils::unCommentSelection(this);
......
......@@ -208,6 +208,7 @@ public:
public Q_SLOTS:
virtual void setFontSettings(const TextEditor::FontSettings &);
virtual void setTabSettings(const TextEditor::TabSettings &);
void setSortedMethodOverview(bool sort);
void switchDeclarationDefinition();
void jumpToDefinition();
......
......@@ -38,8 +38,8 @@ using namespace TextEditor;
using namespace CppTools::Internal;
CodeFormatter::CodeFormatter()
: m_document(0)
, m_indentDepth(0)
: m_indentDepth(0)
, m_tabSize(4)
{
}
......@@ -47,9 +47,9 @@ CodeFormatter::~CodeFormatter()
{
}
void CodeFormatter::setDocument(QTextDocument *document)
void CodeFormatter::setTabSize(int tabSize)
{
m_document = document;
m_tabSize = tabSize;
}
void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
......@@ -59,6 +59,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
bool endedJoined = false;
const int lexerState = tokenizeBlock(block, &endedJoined);
m_tokenIndex = 0;
m_newStates.clear();
if (tokenAt(0).kind() == T_POUND) {
enter(cpp_macro_start);
......@@ -84,7 +85,8 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case namespace_start:
switch (kind) {
case T_LBRACE: turnInto(namespace_open); break;
case T_LBRACE: enter(namespace_open); break;
case T_RBRACE: leave(); break;
} break;
case namespace_open:
......@@ -92,7 +94,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
break;
switch (kind) {
case T_NAMESPACE: enter(namespace_start); break;
case T_RBRACE: leave(); break;
case T_RBRACE: leave(); continue; // always nested in namespace_start
case T_STRUCT:
case T_UNION:
case T_CLASS: enter(class_start); break;
......@@ -103,14 +105,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case class_start:
switch (kind) {
case T_SEMICOLON: leave(); break;
case T_LBRACE: turnInto(class_open); break;
case T_LBRACE: enter(class_open); break;
} break;
case class_open:
if (tryDeclaration())
break;
switch (kind) {
case T_RBRACE: leave(); break;
case T_RBRACE: leave(); continue; // always nested in class_start
case T_STRUCT:
case T_UNION:
case T_CLASS: enter(class_start); break;
......@@ -121,13 +123,19 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case enum_start:
switch (kind) {
case T_SEMICOLON: leave(); break;
case T_LBRACE: turnInto(brace_list_open); break;
case T_LBRACE: enter(enum_open); break;
} break;
case enum_open:
switch (kind) {
case T_RBRACE: leave(); continue; // always nested in enum_start
case T_LBRACE: enter(brace_list_open); break;
} break;
case brace_list_open:
switch (kind) {
case T_RBRACE: leave(); break;
case T_LBRACE: enter(brace_list_open); break; // ### Other, nested brace list?
case T_LBRACE: enter(brace_list_open); break;
} break;
case using_start:
......@@ -156,10 +164,11 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
if (tryExpression(true))
break;
switch (kind) {
case T_RBRACE:
case T_SEMICOLON: leave(true); break;
case T_EQUAL: enter(initializer); break;
case T_LBRACE: turnInto(defun_open); break;
case T_COLON: turnInto(member_init_open); break;
case T_LBRACE: enter(defun_open); break;
case T_COLON: enter(member_init_open); break;
case T_OPERATOR: enter(operator_declaration); break;
} break;
......@@ -211,14 +220,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
case member_init_open:
switch (kind) {
case T_LBRACE: turnInto(defun_open); break;
case T_SEMICOLON: leave(); break; // ### so we don't break completely if it's a bitfield or ternary
case T_SEMICOLON: leave(); continue; // so we don't break completely if it's a bitfield or ternary
} break;
case defun_open:
if (tryStatement())
break;
switch (kind) {
case T_RBRACE: leave(); break;
case T_RBRACE: leave(); continue; // always nested in declaration_start
} break;
case switch_statement:
......@@ -437,9 +446,6 @@ int CodeFormatter::indentFor(const QTextBlock &block)
{
// qDebug() << "indenting for" << block.blockNumber() + 1;
Q_ASSERT(m_document);
Q_ASSERT(m_document == block.document());
requireStatesUntil(block);
correctIndentation(block);
return m_indentDepth;
......@@ -448,7 +454,7 @@ int CodeFormatter::indentFor(const QTextBlock &block)
void CodeFormatter::requireStatesUntil(const QTextBlock &endBlock)
{
QStack<State> previousState = initialState();
QTextBlock it = m_document->firstBlock();
QTextBlock it = endBlock.document()->firstBlock();
for (; it.isValid() && it != endBlock; it = it.next()) {
TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
......@@ -478,14 +484,19 @@ CodeFormatter::State CodeFormatter::state(int belowTop) const
return State();
}
const QVector<CodeFormatter::State> &CodeFormatter::newStatesThisLine() const
{
return m_newStates;
}
int CodeFormatter::tokenIndex() const
{
return m_tokenIndex;
}
int CodeFormatter::tokenIndexFromEnd() const
int CodeFormatter::tokenCount() const
{
return m_tokens.size() - 1 - m_tokenIndex;
return m_tokens.size();
}
const CPlusPlus::Token &CodeFormatter::currentToken() const
......@@ -493,9 +504,12 @@ const CPlusPlus::Token &CodeFormatter::currentToken() const
return m_currentToken;
}
void CodeFormatter::invalidateCache()
void CodeFormatter::invalidateCache(QTextDocument *document)
{
QTextBlock it = m_document->firstBlock();
if (!document)
return;
QTextBlock it = document->firstBlock();
for (; it.isValid(); it = it.next()) {
TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
......@@ -509,7 +523,9 @@ void CodeFormatter::enter(int newState)
{
int savedIndentDepth = m_indentDepth;
onEnter(newState, &m_indentDepth, &savedIndentDepth);
m_currentState.push(State(newState, savedIndentDepth));
State s(newState, savedIndentDepth);
m_currentState.push(s);
m_newStates.push(s);
}
void CodeFormatter::leave(bool statementDone)
......@@ -518,6 +534,9 @@ void CodeFormatter::leave(bool statementDone)
if (m_currentState.top().type == topmost_intro)
return;
if (m_newStates.size() > 0)
m_newStates.pop();
// restore indent depth
State poppedState = m_currentState.pop();
m_indentDepth = poppedState.savedIndentDepth;
......@@ -710,6 +729,24 @@ const Token &CodeFormatter::tokenAt(int idx) const
return m_tokens.at(idx);
}
int CodeFormatter::column(int index) const
{
int col = 0;
if (index > m_currentLine.length())
index = m_currentLine.length();
const QChar tab = QLatin1Char('\t');
for (int i = 0; i < index; i++) {
if (m_currentLine[i] == tab) {
col = ((col / m_tabSize) + 1) * m_tabSize;
} else {
col++;
}
}
return col;
}
QStringRef CodeFormatter::currentTokenText() const
{
return m_currentLine.midRef(m_currentToken.begin(), m_currentToken.length());
......@@ -794,24 +831,45 @@ void CodeFormatter::dump()
QtStyleCodeFormatter::QtStyleCodeFormatter()
: m_indentSize(4)
, m_indentSubstatementBraces(false)
, m_indentSubstatementStatements(true)
, m_indentDeclarationBraces(false)
, m_indentDeclarationMembers(true)
{
}
void QtStyleCodeFormatter::setIndentSize(int size)
{
if (size != m_indentSize) {
m_indentSize = size;
invalidateCache();
}
m_indentSize = size;
}
void QtStyleCodeFormatter::setIndentSubstatementBraces(bool onOff)
{
m_indentSubstatementBraces = onOff;
}
void QtStyleCodeFormatter::setIndentSubstatementStatements(bool onOff)
{
m_indentSubstatementStatements = onOff;
}
void QtStyleCodeFormatter::setIndentDeclarationBraces(bool onOff)
{
m_indentDeclarationBraces = onOff;
}
void QtStyleCodeFormatter::setIndentDeclarationMembers(bool onOff)
{
m_indentDeclarationMembers = onOff;
}
void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
{
const State &parentState = state();
const Token &tk = currentToken();
const int tokenPosition = tk.begin();
const int tokenPosition = column(tk.begin());
const bool firstToken = (tokenIndex() == 0);
const bool lastToken = (tokenIndexFromEnd() == 0);
const bool lastToken = (tokenIndex() == tokenCount() - 1);
switch (newState) {
case namespace_start:
......@@ -865,26 +923,58 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
break;
case member_init_open:
// undo the continuation indent of the parent
*savedIndentDepth = parentState.savedIndentDepth;
if (firstToken)
*indentDepth = tokenPosition + tk.length() + 1;
else
*indentDepth += m_indentSize;
*indentDepth = *savedIndentDepth + m_indentSize;
break;
case defun_open:
case class_open:
case case_cont:
*indentDepth += m_indentSize;
break;
case substatement_open:
if (parentState.type != switch_statement)
case class_open:
case enum_open:
case defun_open:
// undo the continuation indent of the parent
*savedIndentDepth = parentState.savedIndentDepth;
if (firstToken)
*savedIndentDepth = tokenPosition;
*indentDepth = *savedIndentDepth;
if (m_indentDeclarationMembers)
*indentDepth += m_indentSize;
break;
case substatement_open:
if (firstToken) {
*savedIndentDepth = tokenPosition;
*indentDepth = *savedIndentDepth;
} else if (m_indentSubstatementBraces && !m_indentSubstatementStatements) {
// ### The preceding check is quite arbitrary.
// It actually needs another flag to determine whether the closing curly
// should be indented or not
*indentDepth = *savedIndentDepth += m_indentSize;
}
if (m_indentSubstatementStatements) {
if (parentState.type != switch_statement)
*indentDepth += m_indentSize;
}
break;
case brace_list_open:
if (parentState.type != initializer)
*indentDepth = parentState.savedIndentDepth + m_indentSize;
else if (lastToken) {
*savedIndentDepth = state(1).savedIndentDepth;
*indentDepth = *savedIndentDepth + m_indentSize;
}
break;
case block_open:
......@@ -984,16 +1074,27 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
}
break;
case T_LBRACE: {
// function definition - argument list is expression state
if (topState.type == case_cont)
if (topState.type == case_cont) {
*indentDepth = topState.savedIndentDepth;
else if (topState.type == expression && previousState.type == declaration_start)
// function definition - argument list is expression state
} else if (topState.type == expression && previousState.type == declaration_start) {
*indentDepth = previousState.savedIndentDepth;
else if (topState.type != defun_open
&& topState.type != substatement_open
if (m_indentDeclarationBraces)
*indentDepth += m_indentSize;
} else if (topState.type == class_start) {
*indentDepth = topState.savedIndentDepth;
if (m_indentDeclarationBraces)
*indentDepth += m_indentSize;
} else if (topState.type == substatement) {
*indentDepth = topState.savedIndentDepth;
if (m_indentSubstatementBraces)
*indentDepth += m_indentSize;
} else if (topState.type != defun_open
&& topState.type != block_open
&& !topWasMaybeElse)
&& !topWasMaybeElse) {
*indentDepth = topState.savedIndentDepth;
}
break;
}
case T_RBRACE: {
......@@ -1008,7 +1109,8 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
|| type == class_open
|| type == brace_list_open
|| type == namespace_open
|| type == block_open) {
|| type == block_open
|| type == enum_open) {
*indentDepth = state(i).savedIndentDepth;
break;
}
......
......@@ -28,10 +28,12 @@ public:
CodeFormatter();
virtual ~CodeFormatter();
void setDocument(QTextDocument *document);
int indentFor(const QTextBlock &block);
void setTabSize(int tabSize);
static void invalidateCache(QTextDocument *document);
protected:
virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const = 0;
virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth) const = 0;
......@@ -58,7 +60,8 @@ protected:
member_init_open, // After ':' that starts a member initialization list.
enum_start, // After 'enum'
brace_list_open, // Open brace of an enum or static array list.
enum_open, // Brace that opens a enum declaration.
brace_list_open, // Open brace nested inside an enum or for a static array list.
namespace_start, // after the namespace token, before the opening brace.
namespace_open, // Brace that opens a C++ namespace block.
......@@ -125,15 +128,15 @@ protected:
};
State state(int belowTop = 0) const;