Commit b68a16f1 authored by Roberto Raggi's avatar Roberto Raggi

Highlight user defined types.

parent 2a0f901e
......@@ -33,6 +33,7 @@
#include "CppDocument.h"
#include "LookupContext.h"
#include <ASTVisitor.h>
#include <QtCore/QSet>
namespace CPlusPlus {
......@@ -44,6 +45,17 @@ public:
QList<Document::DiagnosticMessage> operator()(AST *ast);
struct Use { // ### remove me
unsigned line;
unsigned column;
unsigned length;
Use(unsigned line = 0, unsigned column = 0, unsigned length = 0)
: line(line), column(column), length(length) {}
};
QList<Use> typeUsages() const;
protected:
using ASTVisitor::visit;
......@@ -51,15 +63,25 @@ protected:
bool warning(AST *ast, const QString &text);
void checkNamespace(NameAST *name);
void addTypeUsage(ClassOrNamespace *b, NameAST *ast);
void addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast);
virtual bool visit(UsingDirectiveAST *);
virtual bool visit(SimpleDeclarationAST *);
virtual bool visit(NamedTypeSpecifierAST *);
virtual bool visit(SimpleNameAST *ast);
virtual bool visit(DestructorNameAST *ast);
virtual bool visit(QualifiedNameAST *ast);
virtual bool visit(TemplateIdAST *ast);
private:
LookupContext _context;
QString _fileName;
QList<Document::DiagnosticMessage> _diagnosticMessages;
QSet<QByteArray> _potentialTypes;
QList<ScopedSymbol *> _scopes;
QList<Use> _typeUsages;
};
} // end of namespace CPlusPlus
......
......@@ -128,12 +128,14 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList<Symbol *> &candid
void FindUsages::reportResult(unsigned tokenIndex)
{
if (_processed.contains(tokenIndex))
const Token &tk = tokenAt(tokenIndex);
if (tk.generated())
return;
else if (_processed.contains(tokenIndex))
return;
_processed.insert(tokenIndex);
const Token &tk = tokenAt(tokenIndex);
const QString lineText = matchingLine(tk);
unsigned line, col;
......
......@@ -779,12 +779,9 @@ void Preprocessor::preprocess(const QString &fileName, const QByteArray &source,
if (! env->isBuiltinMacro(spell)) {
Macro *m = env->resolve(spell);
if (m && ! m->isFunctionLike()) {
QByteArray expandedDefinition;
expandObjectLikeMacro(identifierToken, spell, m, &expandedDefinition);
if (expandedDefinition.trimmed().isEmpty()) {
out(QByteArray(spell.length(), ' '));
continue;
}
// expand object-like macros.
processObjectLikeMacro(identifierToken, spell, m);
continue;
}
}
out(spell);
......
......@@ -265,6 +265,10 @@ protected:
bool findMemberForToken(unsigned tokenIdx, NameAST *ast)
{
const Token &tok = tokenAt(tokenIdx);
if (tok.generated())
return false;
unsigned line, column;
getTokenStartPosition(tokenIdx, &line, &column);
......@@ -303,6 +307,10 @@ protected:
for (TemplateArgumentListAST *arg = ast->template_argument_list; arg; arg = arg->next)
accept(arg->value);
const Token &tok = tokenAt(ast->identifier_token);
if (tok.generated())
return false;
unsigned line, column;
getTokenStartPosition(ast->firstToken(), &line, &column);
......@@ -1781,6 +1789,7 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
m_occurrencesUnusedFormat.clearForeground();
m_occurrencesUnusedFormat.setToolTip(tr("Unused variable"));
m_occurrenceRenameFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES_RENAME));
m_typeFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_TYPE));
// only set the background, we do not want to modify foreground properties set by the syntax highlighter or the link
m_occurrencesFormat.clearForeground();
......@@ -1889,6 +1898,21 @@ void CPPEditor::updateSemanticInfo(const SemanticInfo &semanticInfo)
}
setExtraSelections(UndefinedSymbolSelection, undefinedSymbolSelections);
QList<QTextEdit::ExtraSelection> typeSelections;
foreach (const SemanticInfo::Use &use, semanticInfo.typeUsages) {
QTextCursor cursor(document());
cursor.setPosition(document()->findBlockByNumber(use.line - 1).position() + use.column - 1);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, use.length);
QTextEdit::ExtraSelection sel;
sel.cursor = cursor;
sel.format = m_typeFormat;
typeSelections.append(sel);
}
setExtraSelections(TypeSelection, typeSelections);
}
setExtraSelections(UnusedSymbolSelection, unusedSelections);
......@@ -1987,12 +2011,14 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
Snapshot snapshot;
Document::Ptr doc;
QList<Document::DiagnosticMessage> diagnosticMessages;
QList<SemanticInfo::Use> typeUsages;
if (! source.force && revision == source.revision) {
m_mutex.lock();
snapshot = m_lastSemanticInfo.snapshot; // ### TODO: use the new snapshot.
doc = m_lastSemanticInfo.doc;
diagnosticMessages = m_lastSemanticInfo.diagnosticMessages;
typeUsages = m_lastSemanticInfo.typeUsages;
m_mutex.unlock();
}
......@@ -2003,17 +2029,14 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
doc = snapshot.documentFromSource(preprocessedCode, source.fileName);
doc->check();
Document::Ptr documentInSnapshot = snapshot.document(source.fileName);
if (! documentInSnapshot) {
// use the newly parsed document.
documentInSnapshot = doc;
}
LookupContext context(doc, snapshot);
if (TranslationUnit *unit = doc->translationUnit()) {
CheckUndefinedSymbols checkUndefinedSymbols(unit, context);
diagnosticMessages = checkUndefinedSymbols(unit->ast());
typeUsages.clear();
foreach (const CheckUndefinedSymbols::Use &use, checkUndefinedSymbols.typeUsages()) // ### remove me
typeUsages.append(SemanticInfo::Use(use.line, use.column, use.length));
}
}
......@@ -2035,6 +2058,7 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
semanticInfo.hasD = useTable.hasD;
semanticInfo.forced = source.force;
semanticInfo.diagnosticMessages = diagnosticMessages;
semanticInfo.typeUsages = typeUsages;
return semanticInfo;
}
......@@ -88,7 +88,8 @@ public:
bool forced: 1;
CPlusPlus::Snapshot snapshot;
CPlusPlus::Document::Ptr doc;
LocalUseMap localUses;
LocalUseMap localUses; // ### rename
QList<Use> typeUsages;
QList<CPlusPlus::Document::DiagnosticMessage> diagnosticMessages;
};
......@@ -299,6 +300,7 @@ private:
QTextCharFormat m_occurrencesFormat;
QTextCharFormat m_occurrencesUnusedFormat;
QTextCharFormat m_occurrenceRenameFormat;
QTextCharFormat m_typeFormat;
QList<QTextEdit::ExtraSelection> m_renameSelections;
int m_currentRenameSelection;
......
......@@ -360,11 +360,14 @@ void CppHighlighter::highlightWord(QStringRef word, int position, int length)
{
// try to highlight Qt 'identifiers' like QObject and Q_PROPERTY
// but don't highlight words like 'Query'
if (word.length() > 1
&& word.at(0) == QLatin1Char('Q')
&& (word.at(1).isUpper()
|| word.at(1) == QLatin1Char('_')
|| word.at(1) == QLatin1Char('t'))) {
if (word.length() > 1 && word.at(0) == QLatin1Char('Q')) {
for (int i = 1; i < word.length(); ++i) {
const QChar &ch = word.at(i);
if (! (ch.isUpper() || ch == QLatin1Char('_')))
return;
}
setFormat(position, length, m_formats[CppTypeFormat]);
}
}
......
......@@ -340,6 +340,7 @@ public:
FakeVimSelection,
OtherSelection,
SnippetPlaceholderSelection,
TypeSelection,
NExtraSelectionKinds
};
void setExtraSelections(ExtraSelectionKind kind, const QList<QTextEdit::ExtraSelection> &selections);
......
......@@ -153,12 +153,10 @@ bool CheckStatement::visit(ExpressionOrDeclarationStatementAST *ast)
{
// translationUnit()->warning(ast->firstToken(),
// "ambiguous expression or declaration statement");
if (ast->declaration) {
semantic()->check(ast->declaration, _scope);
_exprType = FullySpecifiedType();
} else {
_exprType = semantic()->check(ast->expression, _scope);
}
semantic()->check(ast->declaration, _scope);
_exprType = semantic()->check(ast->expression, _scope);
return false;
}
......
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