Commit 66a96c86 authored by dt's avatar dt
Browse files

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

parents 19bba275 2d51d0b6
......@@ -51,6 +51,7 @@ void CheckUndefinedSymbols::setGlobalNamespaceBinding(NamespaceBindingPtr global
{
_globalNamespaceBinding = globalNamespaceBinding;
_types.clear();
_protocols.clear();
if (_globalNamespaceBinding) {
QSet<NamespaceBinding *> processed;
......@@ -130,23 +131,43 @@ void CheckUndefinedSymbols::addType(Name *name)
_types.insert(QByteArray(id->chars(), id->size()));
}
void CheckUndefinedSymbols::addProtocol(Name *name)
{
if (!name)
return;
if (Identifier *id = name->identifier())
_protocols.insert(QByteArray(id->chars(), id->size()));
}
bool CheckUndefinedSymbols::isProtocol(const QByteArray &name) const
{
return _protocols.contains(name);
}
void CheckUndefinedSymbols::buildTypeMap(Class *klass)
{
addType(klass->name());
for (unsigned i = 0; i < klass->memberCount(); ++i) {
Symbol *member = klass->memberAt(i);
if (Class *klass = member->asClass()) {
buildTypeMap(klass);
} else if (Enum *e = member->asEnum()) {
addType(e->name());
} else if (ForwardClassDeclaration *fwd = member->asForwardClassDeclaration()) {
addType(fwd->name());
} else if (Declaration *decl = member->asDeclaration()) {
if (decl->isTypedef())
addType(decl->name());
}
buildMemberTypeMap(klass->memberAt(i));
}
}
void CheckUndefinedSymbols::buildMemberTypeMap(Symbol *member)
{
if (member == 0)
return;
if (Class *klass = member->asClass()) {
buildTypeMap(klass);
} else if (Enum *e = member->asEnum()) {
addType(e->name());
} else if (ForwardClassDeclaration *fwd = member->asForwardClassDeclaration()) {
addType(fwd->name());
} else if (Declaration *decl = member->asDeclaration()) {
if (decl->isTypedef())
addType(decl->name());
}
}
......@@ -176,10 +197,16 @@ void CheckUndefinedSymbols::buildTypeMap(NamespaceBinding *binding, QSet<Namespa
addType(fKlass->name());
} else if (ObjCClass *klass = member->asObjCClass()) {
addType(klass->name());
for (unsigned i = 0; i < klass->memberCount(); ++i)
buildMemberTypeMap(klass->memberAt(i));
} else if (ObjCForwardProtocolDeclaration *fProto = member->asObjCForwardProtocolDeclaration()) {
addType(fProto->name());
addProtocol(fProto->name());
} else if (ObjCProtocol *proto = member->asObjCProtocol()) {
addType(proto->name());
addProtocol(proto->name());
for (unsigned i = 0; i < proto->memberCount(); ++i)
buildMemberTypeMap(proto->memberAt(i));
}
}
}
......@@ -454,3 +481,53 @@ bool CheckUndefinedSymbols::visit(SizeofExpressionAST *ast)
return true;
}
bool CheckUndefinedSymbols::visit(ObjCClassDeclarationAST *ast)
{
if (NameAST *nameAST = ast->superclass) {
bool resolvedSuperClassName = false;
if (Name *name = nameAST->name) {
Identifier *id = name->identifier();
const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size());
if (isType(spell))
resolvedSuperClassName = true;
}
if (! resolvedSuperClassName) {
translationUnit()->warning(nameAST->firstToken(),
"expected class-name after ':' token");
}
}
return true;
}
bool CheckUndefinedSymbols::visit(ObjCProtocolRefsAST *ast)
{
for (IdentifierListAST *iter = ast->identifier_list; iter; iter = iter->next) {
if (NameAST *nameAST = iter->name) {
bool resolvedProtocolName = false;
if (Name *name = nameAST->name) {
Identifier *id = name->identifier();
const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size());
if (isProtocol(spell))
resolvedProtocolName = true;
}
if (!resolvedProtocolName) {
char after;
if (iter == ast->identifier_list)
after = '<';
else
after = ',';
translationUnit()->warning(nameAST->firstToken(), "expected protocol name after '%c' token", after);
}
}
}
return false;
}
......@@ -57,7 +57,10 @@ protected:
void addType(Name *name);
void buildTypeMap(Class *klass);
void buildMemberTypeMap(Symbol *member);
void buildTypeMap(NamespaceBinding *binding, QSet<NamespaceBinding *> *processed);
void addProtocol(Name *name);
bool isProtocol(const QByteArray &name) const;
FunctionDeclaratorAST *currentFunctionDeclarator() const;
CompoundStatementAST *compoundStatement() const;
......@@ -91,6 +94,9 @@ protected:
virtual bool visit(CastExpressionAST *ast);
virtual bool visit(SizeofExpressionAST *ast);
virtual bool visit(ObjCClassDeclarationAST *ast);
virtual bool visit(ObjCProtocolRefsAST *ast);
private:
Document::Ptr _doc;
NamespaceBindingPtr _globalNamespaceBinding;
......@@ -99,6 +105,7 @@ private:
QList<TemplateDeclarationAST *> _templateDeclarationStack;
QList<CompoundStatementAST *> _compoundStatementStack;
QSet<QByteArray> _types;
QSet<QByteArray> _protocols;
QSet<QByteArray> _namespaceNames;
};
......
......@@ -161,7 +161,7 @@ public:
Symbol *previousSymbol = switchSymbol(symbol);
accept(symbol->identity());
if (_item)
_item.m_data = QVariant::fromValue(symbol);
_item.data = QVariant::fromValue(symbol);
(void) switchSymbol(previousSymbol);
return switchCompletionItem(previousItem);
}
......@@ -184,8 +184,8 @@ protected:
TextEditor::CompletionItem newCompletionItem(Name *name)
{
TextEditor::CompletionItem item(_collector);
item.m_text = overview.prettyName(name);
item.m_icon = _collector->iconForSymbol(_symbol);
item.text = overview.prettyName(name);
item.icon = _collector->iconForSymbol(_symbol);
return item;
}
......@@ -195,7 +195,7 @@ protected:
virtual void visit(TemplateNameId *name)
{
_item = newCompletionItem(name);
_item.m_text = QLatin1String(name->identifier()->chars());
_item.text = QLatin1String(name->identifier()->chars());
}
virtual void visit(DestructorNameId *name)
......@@ -474,8 +474,8 @@ int CppQuickFixCollector::startCompletion(TextEditor::ITextEditable *editor)
int i = 0;
foreach (QuickFixOperationPtr op, quickFixes) {
TextEditor::CompletionItem item(this);
item.m_text = op->description();
item.m_data = QVariant::fromValue(i);
item.text = op->description();
item.data = QVariant::fromValue(i);
_completions.append(item);
++i;
}
......@@ -494,7 +494,7 @@ void CppQuickFixCollector::complete(const TextEditor::CompletionItem &item)
{
CppEditorSupport *extra = _modelManager->editorSupport(_editor);
const QList<QuickFixOperationPtr> quickFixes = extra->quickFixes();
QuickFixOperationPtr quickFix = quickFixes.at(item.m_data.toInt());
QuickFixOperationPtr quickFix = quickFixes.at(item.data.toInt());
TextEditor::BaseTextEditor *ed = qobject_cast<TextEditor::BaseTextEditor *>(_editor->widget());
quickFix->apply(ed->textCursor());
}
......@@ -508,7 +508,7 @@ CppCodeCompletion::CppCodeCompletion(CppModelManager *manager)
: ICompletionCollector(manager),
m_manager(manager),
m_caseSensitivity(Qt::CaseSensitive),
m_autoInsertBrackets(true),
awesome(true),
m_forcedCompletion(false),
m_completionOperator(T_EOF_SYMBOL)
{
......@@ -531,12 +531,12 @@ void CppCodeCompletion::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity)
bool CppCodeCompletion::autoInsertBrackets() const
{
return m_autoInsertBrackets;
return awesome;
}
void CppCodeCompletion::setAutoInsertBrackets(bool autoInsertBrackets)
{
m_autoInsertBrackets = autoInsertBrackets;
awesome = autoInsertBrackets;
}
bool CppCodeCompletion::isPartialCompletionEnabled() const
......@@ -757,8 +757,8 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
if (m_completionOperator == T_DOXY_COMMENT) {
for (int i = 1; i < T_DOXY_LAST_TAG; ++i) {
TextEditor::CompletionItem item(this);
item.m_text.append(QString::fromLatin1(doxygenTagSpell(i)));
item.m_icon = m_icons.keywordIcon();
item.text.append(QString::fromLatin1(doxygenTagSpell(i)));
item.icon = m_icons.keywordIcon();
m_completions.append(item);
}
......@@ -1148,8 +1148,8 @@ void CppCodeCompletion::addKeywords()
// keyword completion items.
for (int i = T_FIRST_KEYWORD; i < T_FIRST_OBJC_AT_KEYWORD; ++i) {
TextEditor::CompletionItem item(this);
item.m_text = QLatin1String(Token::name(i));
item.m_icon = m_icons.keywordIcon();
item.text = QLatin1String(Token::name(i));
item.icon = m_icons.keywordIcon();
m_completions.append(item);
}
}
......@@ -1164,8 +1164,8 @@ void CppCodeCompletion::addMacros(const LookupContext &context)
foreach (const QString &macroName, definedMacros) {
TextEditor::CompletionItem item(this);
item.m_text = macroName;
item.m_icon = m_icons.macroIcon();
item.text = macroName;
item.icon = m_icons.macroIcon();
m_completions.append(item);
}
}
......@@ -1235,9 +1235,9 @@ bool CppCodeCompletion::completeInclude(const QTextCursor &cursor)
}
foreach (const QString &itemText, m_manager->includesInPath(realPath)) {
TextEditor::CompletionItem item(this);
item.m_text += itemText;
item.text += itemText;
// TODO: Icon for include files
item.m_icon = m_icons.keywordIcon();
item.icon = m_icons.keywordIcon();
m_completions.append(item);
}
}
......@@ -1252,9 +1252,9 @@ bool CppCodeCompletion::completeInclude(const QTextCursor &cursor)
}
foreach (const QString &itemText, m_manager->includesInPath(realPath)) {
TextEditor::CompletionItem item(this);
item.m_text += itemText;
item.text += itemText;
// TODO: Icon for include files
item.m_icon = m_icons.keywordIcon();
item.icon = m_icons.keywordIcon();
m_completions.append(item);
}
}
......@@ -1389,7 +1389,7 @@ bool CppCodeCompletion::completeQtMethod(const QList<TypeOfExpression::Result> &
if (! signatures.contains(signature)) {
signatures.insert(signature);
ci.m_text = signature; // fix the completion item.
ci.text = signature; // fix the completion item.
m_completions.append(ci);
}
......@@ -1446,9 +1446,9 @@ void CppCodeCompletion::completions(QList<TextEditor::CompletionItem> *completio
const QRegExp regExp(keyRegExp, m_caseSensitivity);
foreach (TextEditor::CompletionItem item, m_completions) {
if (regExp.indexIn(item.m_text) == 0) {
item.m_relevance = (key.length() > 0 &&
item.m_text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0;
if (regExp.indexIn(item.text) == 0) {
item.relevance = (key.length() > 0 &&
item.text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0;
(*completions) << item;
}
}
......@@ -1456,7 +1456,7 @@ void CppCodeCompletion::completions(QList<TextEditor::CompletionItem> *completio
m_completionOperator == T_SIGNAL ||
m_completionOperator == T_SLOT) {
foreach (TextEditor::CompletionItem item, m_completions) {
if (item.m_text.startsWith(key, Qt::CaseInsensitive)) {
if (item.text.startsWith(key, Qt::CaseInsensitive)) {
(*completions) << item;
}
}
......@@ -1468,8 +1468,8 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item)
{
Symbol *symbol = 0;
if (item.m_data.isValid())
symbol = item.m_data.value<Symbol *>();
if (item.data.isValid())
symbol = item.data.value<Symbol *>();
QString toInsert;
QString extraChars;
......@@ -1479,19 +1479,19 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item)
bool autoParenthesesEnabled = true;
if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) {
toInsert = item.m_text;
toInsert = item.text;
extraChars += QLatin1Char(')');
} else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL) {
toInsert = item.m_text;
toInsert = item.text;
if (!toInsert.endsWith(QLatin1Char('/')))
extraChars += QLatin1Char((m_completionOperator == T_ANGLE_STRING_LITERAL) ? '>' : '"');
} else {
toInsert = item.m_text;
toInsert = item.text;
//qDebug() << "current symbol:" << overview.prettyName(symbol->name())
//<< overview.prettyType(symbol->type());
if (m_autoInsertBrackets && symbol && symbol->type()) {
if (awesome && symbol && symbol->type()) {
if (Function *function = symbol->type()->asFunctionType()) {
// If the member is a function, automatically place the opening parenthesis,
// except when it might take template parameters.
......@@ -1511,7 +1511,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item)
bool endWithSemicolon = function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON;
// If the function takes no arguments, automatically place the closing parenthesis
if (item.m_duplicateCount == 0 && ! function->hasArguments()) {
if (item.duplicateCount == 0 && ! function->hasArguments()) {
extraChars += QLatin1Char(')');
if (endWithSemicolon)
extraChars += QLatin1Char(';');
......@@ -1560,8 +1560,8 @@ bool CppCodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem
return true;
} else if (m_partialCompletionEnabled && m_completionOperator != T_LPAREN) {
// Compute common prefix
QString firstKey = completionItems.first().m_text;
QString lastKey = completionItems.last().m_text;
QString firstKey = completionItems.first().text;
QString lastKey = completionItems.last().text;
const int length = qMin(firstKey.length(), lastKey.length());
firstKey.truncate(length);
lastKey.truncate(length);
......
......@@ -151,7 +151,7 @@ private:
CppModelManager *m_manager;
Qt::CaseSensitivity m_caseSensitivity;
bool m_autoInsertBrackets;
bool awesome;
bool m_partialCompletionEnabled;
bool m_forcedCompletion;
......
......@@ -534,17 +534,24 @@ static void find_helper(QFutureInterface<Utils::FileSearchResult> &future,
void CppFindReferences::findUsages(Symbol *symbol)
{
_resultWindow->clearContents();
Find::SearchResult *search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchOnly);
connect(search, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem)));
findAll_helper(symbol);
}
void CppFindReferences::renameUsages(Symbol *symbol)
{
Find::SearchResult *search = _resultWindow->startNewSearch();
Find::SearchResult *search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchAndReplace);
connect(search, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem)));
_resultWindow->setShowReplaceUI(true);
connect(search, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)),
SLOT(onReplaceButtonClicked(QString,QList<Find::SearchResultItem>)));
findAll_helper(symbol);
}
......@@ -567,6 +574,60 @@ void CppFindReferences::findAll_helper(Symbol *symbol)
connect(progress, SIGNAL(clicked()), _resultWindow, SLOT(popup()));
}
void CppFindReferences::onReplaceButtonClicked(const QString &text,
const QList<Find::SearchResultItem> &items)
{
if (text.isEmpty())
return;
QHash<QString, QList<Find::SearchResultItem> > changes;
foreach (const Find::SearchResultItem &item, items)
changes[item.fileName].append(item);
QHashIterator<QString, QList<Find::SearchResultItem> > it(changes);
while (it.hasNext()) {
it.next();
const QString fileName = it.key();
QFile file(fileName);
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
// ### set the encoding
const QString plainText = stream.readAll();
file.close();
QTextDocument doc;
doc.setPlainText(plainText);
QList<QTextCursor> cursors;
const QList<Find::SearchResultItem> items = it.value();
foreach (const Find::SearchResultItem &item, items) {
const int blockNumber = item.lineNumber - 1;
QTextCursor tc(doc.findBlockByNumber(blockNumber));
tc.setPosition(tc.position() + item.searchTermStart);
tc.setPosition(tc.position() + item.searchTermLength,
QTextCursor::KeepAnchor);
cursors.append(tc);
}
foreach (QTextCursor tc, cursors)
tc.insertText(text);
QFile newFile(fileName);
if (newFile.open(QFile::WriteOnly)) {
QTextStream stream(&newFile);
// ### set the encoding
stream << doc.toPlainText();
}
}
}
const QStringList fileNames = changes.keys();
_modelManager->updateSourceFiles(fileNames);
}
void CppFindReferences::displayResult(int index)
{
Utils::FileSearchResult result = m_watcher.future().resultAt(index);
......
......@@ -70,6 +70,7 @@ private Q_SLOTS:
void displayResult(int);
void searchFinished();
void openEditor(const Find::SearchResultItem &item);
void onReplaceButtonClicked(const QString &text, const QList<Find::SearchResultItem> &items);
private:
void findAll_helper(CPlusPlus::Symbol *symbol);
......
......@@ -87,6 +87,7 @@ SearchResultWindow::SearchResultWindow()
connect(m_searchResultTreeView, SIGNAL(jumpToSearchResult(int,bool)),
this, SLOT(handleJumpToSearchResult(int,bool)));
connect(m_expandCollapseToolButton, SIGNAL(toggled(bool)), this, SLOT(handleExpandCollapseToolButton(bool)));
connect(m_replaceTextEdit, SIGNAL(returnPressed()), this, SLOT(handleReplaceButton()));
connect(m_replaceButton, SIGNAL(clicked()), this, SLOT(handleReplaceButton()));
readSettings();
......
......@@ -52,13 +52,13 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
foreach (const QString &word, edit->keywords()) {
TextEditor::CompletionItem item(this);
item.m_text = word;
item.text = word;
m_completions.append(item);
}
foreach (const QString &word, edit->words()) {
TextEditor::CompletionItem item(this);
item.m_text = word;
item.text = word;
m_completions.append(item);
}
......@@ -71,7 +71,7 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
foreach (const QString &word, visitor(program, m_startPosition)) {
TextEditor::CompletionItem item(this);
item.m_text = word;
item.text = word;
m_completions.append(item);
}
}
......@@ -120,9 +120,9 @@ void QmlCodeCompletion::completions(QList<TextEditor::CompletionItem> *completio
const QRegExp regExp(keyRegExp, Qt::CaseSensitive);
foreach (TextEditor::CompletionItem item, m_completions) {
if (regExp.indexIn(item.m_text) == 0) {
item.m_relevance = (key.length() > 0 &&
item.m_text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0;
if (regExp.indexIn(item.text) == 0) {
item.relevance = (key.length() > 0 &&
item.text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0;
(*completions) << item;
}
}
......@@ -131,7 +131,7 @@ void QmlCodeCompletion::completions(QList<TextEditor::CompletionItem> *completio
void QmlCodeCompletion::complete(const TextEditor::CompletionItem &item)
{
const QString toInsert = item.m_text;
const QString toInsert = item.text;
const int length = m_editor->position() - m_startPosition;
m_editor->setCurPos(m_startPosition);
m_editor->replace(length, toInsert);
......@@ -144,8 +144,8 @@ bool QmlCodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem
return true;
} else {
// Compute common prefix
QString firstKey = completionItems.first().m_text;
QString lastKey = completionItems.last().m_text;
QString firstKey = completionItems.first().text;
QString lastKey = completionItems.last().text;
const int length = qMin(firstKey.length(), lastKey.length());
firstKey.truncate(length);
lastKey.truncate(length);
......
......@@ -55,7 +55,7 @@ int QtScriptCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
foreach (const QString &word, edit->words()) {
TextEditor::CompletionItem item(this);
item.m_text = word;
item.text = word;
m_completions.append(item);
}
......@@ -102,9 +102,9 @@ void QtScriptCodeCompletion::completions(QList<TextEditor::CompletionItem> *comp
const QRegExp regExp(keyRegExp, Qt::CaseSensitive);
foreach (TextEditor::CompletionItem item, m_completions) {
if (regExp.indexIn(item.m_text) == 0) {
item.m_relevance = (key.length() > 0 &&
item.m_text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0;
if (regExp.indexIn(item.text) == 0) {
item.relevance = (key.length() > 0 &&
item.text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0;
(*completions) << item;
}
}
......@@ -113,7 +113,7 @@ void QtScriptCodeCompletion::completions(QList<TextEditor::CompletionItem> *comp
void QtScriptCodeCompletion::complete(const TextEditor::CompletionItem &item)
{
const QString toInsert = item.m_text;
const QString toInsert = item.text;
const int length = m_editor->position() - m_startPosition;
m_editor->setCurPos(m_startPosition);
m_editor->replace(length, toInsert);
......@@ -126,8 +126,8 @@ bool QtScriptCodeCompletion::partiallyComplete(const QList<TextEditor::Completio
return true;
} else {
// Compute common prefix
QString firstKey = completionItems.first().m_text;
QString lastKey = completionItems.last().m_text;
QString firstKey = completionItems.first().text;
QString lastKey = completionItems.last().text;
const int length = qMin(firstKey.length(), lastKey.length());
firstKey.truncate(length);
lastKey.truncate(length);
......