forked from qt-creator/qt-creator
Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline
This commit is contained in:
@@ -36,13 +36,100 @@
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class BackwardsScanner
|
||||
{
|
||||
enum { MAX_BLOCK_COUNT = 10 };
|
||||
|
||||
public:
|
||||
BackwardsScanner(const QTextCursor &cursor)
|
||||
: _offset(0)
|
||||
, _blocksTokenized(0)
|
||||
, _block(cursor.block())
|
||||
{
|
||||
_tokenize.setSkipComments(true);
|
||||
_text = _block.text().left(cursor.position() - cursor.block().position());
|
||||
_tokens.append(_tokenize(_text, previousBlockState(_block)));
|
||||
}
|
||||
|
||||
QList<SimpleToken> tokens() const { return _tokens; }
|
||||
|
||||
const SimpleToken &operator[](int i)
|
||||
{
|
||||
while (_offset + i < 0) {
|
||||
_block = _block.previous();
|
||||
if (_blocksTokenized == MAX_BLOCK_COUNT || !_block.isValid()) {
|
||||
++_offset;
|
||||
_tokens.prepend(SimpleToken()); // sentinel
|
||||
break;
|
||||
} else {
|
||||
++_blocksTokenized;
|
||||
|
||||
QString blockText = _block.text();
|
||||
_text.prepend(blockText);
|
||||
QList<SimpleToken> adaptedTokens;
|
||||
for (int i = 0; i < _tokens.size(); ++i) {
|
||||
const SimpleToken &t = _tokens.at(i);
|
||||
const int position = t.position() + blockText.length();
|
||||
adaptedTokens.append(SimpleToken(t.kind(),
|
||||
position,
|
||||
t.length(),
|
||||
_text.midRef(position, t.length())));
|
||||
}
|
||||
|
||||
_tokens = _tokenize(blockText, previousBlockState(_block));
|
||||
_offset += _tokens.size();
|
||||
_tokens += adaptedTokens;
|
||||
}
|
||||
}
|
||||
|
||||
return _tokens.at(_offset + i);
|
||||
}
|
||||
|
||||
int startPosition() const
|
||||
{ return _block.position(); }
|
||||
|
||||
const QString &text() const
|
||||
{ return _text; }
|
||||
|
||||
QString text(int begin, int end) const
|
||||
{
|
||||
const SimpleToken &firstToken = _tokens.at(begin + _offset);
|
||||
const SimpleToken &lastToken = _tokens.at(end + _offset - 1);
|
||||
return _text.mid(firstToken.begin(), lastToken.end() - firstToken.begin());
|
||||
}
|
||||
|
||||
int previousBlockState(const QTextBlock &block)
|
||||
{
|
||||
const QTextBlock prevBlock = block.previous();
|
||||
if (prevBlock.isValid()) {
|
||||
int state = prevBlock.userState();
|
||||
|
||||
if (state != -1)
|
||||
return state;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
QList<SimpleToken> _tokens;
|
||||
int _offset;
|
||||
int _blocksTokenized;
|
||||
QTextBlock _block;
|
||||
QString _text;
|
||||
SimpleLexer _tokenize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ExpressionUnderCursor::ExpressionUnderCursor()
|
||||
{ }
|
||||
|
||||
ExpressionUnderCursor::~ExpressionUnderCursor()
|
||||
{ }
|
||||
|
||||
int ExpressionUnderCursor::startOfMatchingBrace(const QList<SimpleToken> &tk, int index)
|
||||
int ExpressionUnderCursor::startOfMatchingBrace(BackwardsScanner &tk, int index)
|
||||
{
|
||||
if (tk[index - 1].is(T_RPAREN)) {
|
||||
int i = index - 1;
|
||||
@@ -54,7 +141,7 @@ int ExpressionUnderCursor::startOfMatchingBrace(const QList<SimpleToken> &tk, in
|
||||
} else if (tk[i].is(T_RPAREN))
|
||||
--count;
|
||||
--i;
|
||||
} while (count != 0 && i > -1);
|
||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||
} else if (tk[index - 1].is(T_RBRACKET)) {
|
||||
int i = index - 1;
|
||||
int count = 0;
|
||||
@@ -65,7 +152,7 @@ int ExpressionUnderCursor::startOfMatchingBrace(const QList<SimpleToken> &tk, in
|
||||
} else if (tk[i].is(T_RBRACKET))
|
||||
--count;
|
||||
--i;
|
||||
} while (count != 0 && i > -1);
|
||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||
} else if (tk[index - 1].is(T_GREATER)) {
|
||||
int i = index - 1;
|
||||
int count = 0;
|
||||
@@ -76,13 +163,13 @@ int ExpressionUnderCursor::startOfMatchingBrace(const QList<SimpleToken> &tk, in
|
||||
} else if (tk[i].is(T_GREATER))
|
||||
--count;
|
||||
--i;
|
||||
} while (count != 0 && i > -1);
|
||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int ExpressionUnderCursor::startOfExpression(const QList<SimpleToken> &tk, int index)
|
||||
int ExpressionUnderCursor::startOfExpression(BackwardsScanner &tk, int index)
|
||||
{
|
||||
// tk is a reference to a const QList. So, don't worry about [] access.
|
||||
// ### TODO implement multiline support. It should be pretty easy.
|
||||
@@ -178,95 +265,37 @@ bool ExpressionUnderCursor::isAccessToken(const SimpleToken &tk)
|
||||
} // switch
|
||||
}
|
||||
|
||||
int ExpressionUnderCursor::previousBlockState(const QTextBlock &block)
|
||||
{
|
||||
const QTextBlock prevBlock = block.previous();
|
||||
if (prevBlock.isValid()) {
|
||||
int state = prevBlock.userState();
|
||||
|
||||
if (state != -1)
|
||||
return state;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExpressionUnderCursor::init(const QTextCursor &cursor,
|
||||
QList<SimpleToken> *tokens,
|
||||
QString *text,
|
||||
int *startPosition)
|
||||
{
|
||||
enum { MAX_BLOCK_COUNT = 5 };
|
||||
|
||||
QTextBlock block = cursor.block();
|
||||
QTextBlock initialBlock = block;
|
||||
for (int i = 0; i < MAX_BLOCK_COUNT; ++i) {
|
||||
if (! initialBlock.previous().isValid())
|
||||
break;
|
||||
|
||||
initialBlock = initialBlock.previous();
|
||||
}
|
||||
|
||||
QTextBlock it = initialBlock;
|
||||
for (; it.isValid(); it = it.next()) {
|
||||
QString textBlock = it.text();
|
||||
|
||||
if (it == block)
|
||||
textBlock = textBlock.left(cursor.position() - cursor.block().position());
|
||||
|
||||
text->append(textBlock);
|
||||
|
||||
if (it == block)
|
||||
break;
|
||||
|
||||
text->append(QLatin1Char('\n'));
|
||||
}
|
||||
|
||||
SimpleLexer tokenize;
|
||||
tokenize.setSkipComments(true);
|
||||
tokens->append(tokenize(*text, previousBlockState(initialBlock)));
|
||||
tokens->prepend(SimpleToken()); // sentinel
|
||||
|
||||
if (startPosition)
|
||||
*startPosition = initialBlock.position();
|
||||
}
|
||||
|
||||
QString ExpressionUnderCursor::operator()(const QTextCursor &cursor)
|
||||
{
|
||||
QList<SimpleToken> tokens;
|
||||
QString text;
|
||||
|
||||
init(cursor, &tokens, &text);
|
||||
BackwardsScanner scanner(cursor);
|
||||
|
||||
_jumpedComma = false;
|
||||
|
||||
const int i = startOfExpression(tokens, tokens.size());
|
||||
if (i == tokens.size())
|
||||
const int initialSize = scanner.tokens().size();
|
||||
const int i = startOfExpression(scanner, initialSize);
|
||||
if (i == initialSize)
|
||||
return QString();
|
||||
|
||||
return text.mid(tokens.at(i).position(),
|
||||
tokens.last().position() + tokens.last().length()
|
||||
- tokens.at(i).position());
|
||||
return scanner.text(i, initialSize);
|
||||
}
|
||||
|
||||
int ExpressionUnderCursor::startOfFunctionCall(const QTextCursor &cursor)
|
||||
{
|
||||
QList<SimpleToken> tokens;
|
||||
QString text;
|
||||
int startPosition;
|
||||
|
||||
init(cursor, &tokens, &text, &startPosition);
|
||||
BackwardsScanner scanner(cursor);
|
||||
|
||||
int index = tokens.size();
|
||||
int index = scanner.tokens().size();
|
||||
|
||||
forever {
|
||||
const SimpleToken &tk = tokens.at(index - 1);
|
||||
const SimpleToken &tk = scanner[index - 1];
|
||||
|
||||
if (tk.is(T_EOF_SYMBOL))
|
||||
break;
|
||||
else if (tk.is(T_LPAREN))
|
||||
return startPosition + tk.position();
|
||||
return scanner.startPosition() + tk.position();
|
||||
else if (tk.is(T_RPAREN)) {
|
||||
int matchingBrace = startOfMatchingBrace(tokens, index);
|
||||
int matchingBrace = startOfMatchingBrace(scanner, index);
|
||||
|
||||
if (matchingBrace == index) // If no matching brace found
|
||||
return -1;
|
||||
|
||||
@@ -41,6 +41,7 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class BackwardsScanner;
|
||||
class SimpleToken;
|
||||
|
||||
class CPLUSPLUS_EXPORT ExpressionUnderCursor
|
||||
@@ -53,13 +54,8 @@ public:
|
||||
int startOfFunctionCall(const QTextCursor &cursor);
|
||||
|
||||
private:
|
||||
void init(const QTextCursor &cursor,
|
||||
QList<SimpleToken> *tokens,
|
||||
QString *text,
|
||||
int *startPosition = 0);
|
||||
|
||||
int startOfMatchingBrace(const QList<SimpleToken> &tk, int index);
|
||||
int startOfExpression(const QList<SimpleToken> &tk, int index);
|
||||
int startOfMatchingBrace(BackwardsScanner &tk, int index);
|
||||
int startOfExpression(BackwardsScanner &tk, int index);
|
||||
int previousBlockState(const QTextBlock &block);
|
||||
bool isAccessToken(const SimpleToken &tk);
|
||||
|
||||
|
||||
@@ -351,14 +351,10 @@ void LookupContext::expand(const QList<Scope *> &scopes, QList<Scope *> *expande
|
||||
}
|
||||
}
|
||||
|
||||
void LookupContext::expandNamespace(Scope *scope,
|
||||
void LookupContext::expandNamespace(Namespace *ns,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const
|
||||
{
|
||||
Namespace *ns = scope->owner()->asNamespace();
|
||||
if (! ns)
|
||||
return;
|
||||
|
||||
if (Name *nsName = ns->name()) {
|
||||
const QList<Symbol *> namespaceList = resolveNamespace(nsName, visibleScopes);
|
||||
foreach (Symbol *otherNs, namespaceList) {
|
||||
@@ -368,10 +364,10 @@ void LookupContext::expandNamespace(Scope *scope,
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < scope->symbolCount(); ++i) { // ### make me fast
|
||||
Symbol *symbol = scope->symbolAt(i);
|
||||
if (Namespace *ns = symbol->asNamespace()) {
|
||||
if (! ns->name()) {
|
||||
for (unsigned i = 0; i < ns->memberCount(); ++i) { // ### make me fast
|
||||
Symbol *symbol = ns->memberAt(i);
|
||||
if (Namespace *otherNs = symbol->asNamespace()) {
|
||||
if (! otherNs->name()) {
|
||||
expand(ns->members(), visibleScopes, expandedScopes);
|
||||
}
|
||||
} else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) {
|
||||
@@ -386,16 +382,12 @@ void LookupContext::expandNamespace(Scope *scope,
|
||||
}
|
||||
}
|
||||
|
||||
void LookupContext::expandClass(Scope *scope,
|
||||
void LookupContext::expandClass(Class *klass,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const
|
||||
{
|
||||
Class *klass = scope->owner()->asClass();
|
||||
if (! klass)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < scope->symbolCount(); ++i) {
|
||||
Symbol *symbol = scope->symbolAt(i);
|
||||
for (unsigned i = 0; i < klass->memberCount(); ++i) {
|
||||
Symbol *symbol = klass->memberAt(i);
|
||||
if (Class *nestedClass = symbol->asClass()) {
|
||||
if (! nestedClass->name()) {
|
||||
expand(nestedClass->members(), visibleScopes, expandedScopes);
|
||||
@@ -442,12 +434,12 @@ void LookupContext::expandClass(Scope *scope,
|
||||
}
|
||||
}
|
||||
|
||||
void LookupContext::expandBlock(Scope *scope,
|
||||
void LookupContext::expandBlock(Block *blockSymbol,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const
|
||||
{
|
||||
for (unsigned i = 0; i < scope->symbolCount(); ++i) {
|
||||
Symbol *symbol = scope->symbolAt(i);
|
||||
for (unsigned i = 0; i < blockSymbol->memberCount(); ++i) {
|
||||
Symbol *symbol = blockSymbol->memberAt(i);
|
||||
if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) {
|
||||
const QList<Symbol *> candidates = resolveNamespace(u->name(),
|
||||
visibleScopes);
|
||||
@@ -460,13 +452,13 @@ void LookupContext::expandBlock(Scope *scope,
|
||||
}
|
||||
}
|
||||
|
||||
void LookupContext::expandFunction(Scope *scope,
|
||||
void LookupContext::expandFunction(Function *function,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const
|
||||
{
|
||||
Function *function = scope->owner()->asFunction();
|
||||
if (! expandedScopes->contains(function->arguments()))
|
||||
expandedScopes->append(function->arguments());
|
||||
|
||||
if (QualifiedNameId *q = function->name()->asQualifiedNameId()) {
|
||||
Name *nestedNameSpec = 0;
|
||||
if (q->nameCount() == 1)
|
||||
@@ -491,15 +483,13 @@ void LookupContext::expand(Scope *scope,
|
||||
|
||||
expandedScopes->append(scope);
|
||||
|
||||
if (scope->isNamespaceScope()) {
|
||||
expandNamespace(scope, visibleScopes, expandedScopes);
|
||||
} else if (scope->isClassScope()) {
|
||||
expandClass(scope, visibleScopes, expandedScopes);
|
||||
} else if (scope->isBlockScope()) {
|
||||
expandBlock(scope, visibleScopes, expandedScopes);
|
||||
} else if (scope->isFunctionScope()) {
|
||||
expandFunction(scope, visibleScopes, expandedScopes);
|
||||
} else if (scope->isPrototypeScope()) {
|
||||
//qDebug() << "prototype scope" << overview.prettyName(scope->owner()->name());
|
||||
if (Namespace *ns = scope->owner()->asNamespace()) {
|
||||
expandNamespace(ns, visibleScopes, expandedScopes);
|
||||
} else if (Class *klass = scope->owner()->asClass()) {
|
||||
expandClass(klass, visibleScopes, expandedScopes);
|
||||
} else if (Block *block = scope->owner()->asBlock()) {
|
||||
expandBlock(block, visibleScopes, expandedScopes);
|
||||
} else if (Function *fun = scope->owner()->asFunction()) {
|
||||
expandFunction(fun, visibleScopes, expandedScopes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,19 +110,19 @@ public:
|
||||
void expand(Scope *scope, const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const;
|
||||
|
||||
void expandNamespace(Scope *scope,
|
||||
void expandNamespace(Namespace *namespaceSymbol,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const;
|
||||
|
||||
void expandClass(Scope *scope,
|
||||
void expandClass(Class *classSymbol,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const;
|
||||
|
||||
void expandBlock(Scope *scope,
|
||||
void expandBlock(Block *blockSymbol,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const;
|
||||
|
||||
void expandFunction(Scope *scope,
|
||||
void expandFunction(Function *functionSymbol,
|
||||
const QList<Scope *> &visibleScopes,
|
||||
QList<Scope *> *expandedScopes) const;
|
||||
|
||||
|
||||
@@ -41,6 +41,13 @@ class SimpleLexer;
|
||||
class CPLUSPLUS_EXPORT SimpleToken
|
||||
{
|
||||
public:
|
||||
SimpleToken(int kind, int position, int length, const QStringRef &text)
|
||||
: _kind(kind)
|
||||
, _position(position)
|
||||
, _length(length)
|
||||
, _text(text)
|
||||
{ }
|
||||
|
||||
SimpleToken()
|
||||
: _kind(0),
|
||||
_position(0),
|
||||
|
||||
@@ -364,7 +364,8 @@ void TypePrettyPrinter::space()
|
||||
|
||||
const QChar ch = _text.at(_text.length() - 1);
|
||||
|
||||
if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')'))
|
||||
if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')')
|
||||
|| ch == QLatin1Char('>'))
|
||||
_text += QLatin1Char(' ');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user