Commit 678f7d3e authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Fixed `look at symbol under cursor' when symbol is a Qt method (e.g. a signal).

Done with: erikv
parent a67e8899
......@@ -119,7 +119,7 @@ QStringRef BackwardsScanner::textRef(int index) const
return _text.midRef(firstToken.begin(), firstToken.length());
}
int BackwardsScanner::previousBlockState(const QTextBlock &block) const
int BackwardsScanner::previousBlockState(const QTextBlock &block)
{
const QTextBlock prevBlock = block.previous();
......
......@@ -67,7 +67,7 @@ public:
int startOfMatchingBrace(int index) const;
int startOfBlock(int index) const;
int previousBlockState(const QTextBlock &block) const;
static int previousBlockState(const QTextBlock &block);
int size() const;
......
......@@ -56,7 +56,6 @@ public:
private:
int startOfExpression(BackwardsScanner &tk, int index);
int startOfExpression_helper(BackwardsScanner &tk, int index);
int previousBlockState(const QTextBlock &block);
bool isAccessToken(const SimpleToken &tk);
private:
......
......@@ -120,6 +120,25 @@ QList<Scope *> ResolveExpression::visibleScopes(const LookupItem &result) const
bool ResolveExpression::visit(BinaryExpressionAST *ast)
{
if (tokenKind(ast->binary_op_token) == T_COMMA && ast->right_expression && ast->right_expression->asQtMethod() != 0) {
if (ast->left_expression && ast->left_expression->asQtMethod() != 0)
thisObject();
else
accept(ast->left_expression);
QtMethodAST *qtMethod = ast->right_expression->asQtMethod();
if (DeclaratorAST *d = qtMethod->declarator) {
if (d->core_declarator) {
if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId())
if (NameAST *nameAST = declaratorId->name)
_results = resolveMemberExpression(_results, T_ARROW, nameAST->name);
}
}
return false;
}
accept(ast->left_expression);
return false;
}
......@@ -263,9 +282,15 @@ bool ResolveExpression::visit(BoolLiteralAST *)
}
bool ResolveExpression::visit(ThisExpressionAST *)
{
thisObject();
return false;
}
void ResolveExpression::thisObject()
{
if (! _context.symbol())
return false;
return;
Scope *scope = _context.symbol()->scope();
for (; scope; scope = scope->enclosingScope()) {
......@@ -290,7 +315,6 @@ bool ResolveExpression::visit(ThisExpressionAST *)
}
}
}
return false;
}
bool ResolveExpression::visit(CompoundExpressionAST *ast)
......
......@@ -63,6 +63,7 @@ public:
protected:
QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
void thisObject();
void addResult(const FullySpecifiedType &ty, Symbol *symbol = 0);
void addResult(const LookupItem &result);
void addResults(const QList<LookupItem> &results);
......
......@@ -28,6 +28,7 @@
**************************************************************************/
#include "TokenUnderCursor.h"
#include "BackwardsScanner.h"
#include <Token.h>
#include <QTextCursor>
......@@ -52,7 +53,7 @@ SimpleToken TokenUnderCursor::operator()(const QTextCursor &cursor, QTextBlock *
int column = cursor.position() - cursor.block().position();
_text = block.text();
_tokens = tokenize(_text, previousBlockState(block));
_tokens = tokenize(_text, BackwardsScanner::previousBlockState(block));
for (int index = _tokens.size() - 1; index != -1; --index) {
const SimpleToken &tk = _tokens.at(index);
if (tk.position() < column) {
......@@ -64,15 +65,3 @@ SimpleToken TokenUnderCursor::operator()(const QTextCursor &cursor, QTextBlock *
return SimpleToken();
}
int TokenUnderCursor::previousBlockState(const QTextBlock &block) const
{
const QTextBlock prevBlock = block.previous();
if (prevBlock.isValid()) {
int state = prevBlock.userState();
if (state != -1)
return state;
}
return 0;
}
......@@ -52,8 +52,6 @@ public:
{ return _tokens; }
private:
int previousBlockState(const QTextBlock &block) const;
QList<SimpleToken> _tokens;
QString _text;
};
......
......@@ -1347,40 +1347,96 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
tc.movePosition(QTextCursor::Right);
}
static TokenUnderCursor tokenUnderCursor;
QTextBlock block;
const SimpleToken tk = tokenUnderCursor(tc, &block);
const int beginOfToken = block.position() + tk.begin();
const int endOfToken = block.position() + tk.end();
// Handle include directives
if (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)) {
const unsigned lineno = cursor.blockNumber() + 1;
foreach (const Document::Include &incl, doc->includes()) {
if (incl.line() == lineno && incl.resolved()) {
link.fileName = incl.fileName();
link.begin = beginOfToken + 1;
link.end = endOfToken - 1;
return link;
int beginOfToken = 0;
int endOfToken = 0;
SimpleLexer tokenize;
tokenize.setQtMocRunEnabled(true);
const QString blockText = cursor.block().text();
const QList<SimpleToken> tokens = tokenize(blockText, BackwardsScanner::previousBlockState(cursor.block()));
bool recognizedQtMethod = false;
for (int i = 0; i < tokens.size(); ++i) {
const SimpleToken &tk = tokens.at(i);
if (column >= tk.begin() && column <= tk.end()) {
if (i >= 2 && tokens.at(i).is(T_IDENTIFIER) && tokens.at(i - 1).is(T_LPAREN)
&& (tokens.at(i - 2).is(T_SIGNAL) || tokens.at(i - 2).is(T_SLOT))) {
// token[i] == T_IDENTIFIER
// token[i + 1] == T_LPAREN
// token[.....] == ....
// token[i + n] == T_RPAREN
if (i + 1 < tokens.size() && tokens.at(i + 1).is(T_LPAREN)) {
// skip matched parenthesis
int j = i - 1;
int depth = 0;
for (; j < tokens.size(); ++j) {
if (tokens.at(j).is(T_LPAREN))
++depth;
else if (tokens.at(j).is(T_RPAREN)) {
if (! --depth)
break;
}
}
if (j < tokens.size()) {
QTextBlock block = cursor.block();
beginOfToken = block.position() + tokens.at(i).begin();
endOfToken = block.position() + tokens.at(i).end();
tc.setPosition(block.position() + tokens.at(j).end());
recognizedQtMethod = true;
}
}
}
break;
}
}
if (tk.isNot(T_IDENTIFIER))
return link;
if (! recognizedQtMethod) {
static TokenUnderCursor tokenUnderCursor;
QTextBlock block;
const SimpleToken tk = tokenUnderCursor(tc, &block);
beginOfToken = block.position() + tk.begin();
endOfToken = block.position() + tk.end();
// Handle include directives
if (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)) {
const unsigned lineno = cursor.blockNumber() + 1;
foreach (const Document::Include &incl, doc->includes()) {
if (incl.line() == lineno && incl.resolved()) {
link.fileName = incl.fileName();
link.begin = beginOfToken + 1;
link.end = endOfToken - 1;
return link;
}
}
}
if (tk.isNot(T_IDENTIFIER))
return link;
tc.setPosition(endOfToken);
}
// Find the last symbol up to the cursor position
Symbol *lastSymbol = doc->findSymbolAt(line, column);
if (!lastSymbol)
return link;
tc.setPosition(endOfToken);
// Evaluate the type of the expression under the cursor
ExpressionUnderCursor expressionUnderCursor;
const QString expression = expressionUnderCursor(tc);
TypeOfExpression typeOfExpression;
typeOfExpression.setSnapshot(snapshot);
QList<LookupItem> resolvedSymbols =
......
Supports Markdown
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