Commit 3ae4f07b authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

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

parents e5c6a29f 985aa572
......@@ -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(' ');
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment