forked from qt-creator/qt-creator
Context-sensitive highlighting.
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
|
||||
#include <QtDebug>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
@@ -694,7 +695,6 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour
|
||||
|
||||
else if (_dot->whitespace) {
|
||||
TokenIterator begin = _tokens.constBegin();
|
||||
Q_ASSERT(begin != first);
|
||||
|
||||
const unsigned endOfPreviousToken = (_dot - 1)->end();
|
||||
const unsigned beginOfToken = _dot->begin();
|
||||
|
||||
@@ -392,12 +392,67 @@ void CPPEditor::updateMethodBoxIndex()
|
||||
lastIndex = index;
|
||||
}
|
||||
|
||||
QList<QTextEdit::ExtraSelection> selections;
|
||||
|
||||
if (lastIndex.isValid()) {
|
||||
bool blocked = m_methodCombo->blockSignals(true);
|
||||
m_methodCombo->setCurrentIndex(lastIndex.row());
|
||||
updateMethodBoxToolTip();
|
||||
(void) m_methodCombo->blockSignals(blocked);
|
||||
}
|
||||
|
||||
#ifdef QTCREATOR_WITH_ADVANCED_HIGHLIGHTER
|
||||
Snapshot snapshot = m_modelManager->snapshot();
|
||||
Document::Ptr thisDocument = snapshot.value(file()->fileName());
|
||||
if (! thisDocument)
|
||||
return;
|
||||
|
||||
if (Symbol *symbol = thisDocument->findSymbolAt(line, column)) {
|
||||
QTextCursor tc = textCursor();
|
||||
tc.movePosition(QTextCursor::EndOfWord);
|
||||
|
||||
ExpressionUnderCursor expressionUnderCursor;
|
||||
|
||||
const QString expression = expressionUnderCursor(tc);
|
||||
//qDebug() << "expression:" << expression;
|
||||
|
||||
TypeOfExpression typeOfExpression;
|
||||
typeOfExpression.setSnapshot(m_modelManager->snapshot());
|
||||
|
||||
const QList<TypeOfExpression::Result> results =
|
||||
typeOfExpression(expression, thisDocument, symbol, TypeOfExpression::Preprocess);
|
||||
|
||||
LookupContext context = typeOfExpression.lookupContext();
|
||||
|
||||
foreach (const TypeOfExpression::Result &result, results) {
|
||||
FullySpecifiedType ty = result.first;
|
||||
Symbol *symbol = result.second;
|
||||
|
||||
if (file()->fileName() != symbol->fileName())
|
||||
continue;
|
||||
|
||||
if (symbol) {
|
||||
int column = symbol->column();
|
||||
|
||||
if (column != 0)
|
||||
--column;
|
||||
|
||||
QTextCursor c(document()->findBlockByNumber(symbol->line() - 1));
|
||||
c.setPosition(c.position() + column);
|
||||
c.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
||||
|
||||
QTextEdit::ExtraSelection sel;
|
||||
sel.cursor = c;
|
||||
sel.format.setBackground(Qt::darkYellow);
|
||||
|
||||
selections.append(sel);
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setExtraSelections(CodeSemanticsSelection, selections);
|
||||
#endif // QTCREATOR_WITH_ADVANCED_HIGHLIGHTER
|
||||
}
|
||||
|
||||
void CPPEditor::updateMethodBoxToolTip()
|
||||
@@ -893,5 +948,14 @@ TextEditor::ITextEditor *CPPEditor::openCppEditorAt(const QString &fileName,
|
||||
bool CPPEditor::openEditorAt(Symbol *s)
|
||||
{
|
||||
const QString fileName = QString::fromUtf8(s->fileName(), s->fileNameLength());
|
||||
return openCppEditorAt(fileName, s->line(), s->column());
|
||||
|
||||
#ifdef QTCREATOR_WITH_ADVANCED_HIGHLIGHTER
|
||||
unsigned column = s->column();
|
||||
if (column)
|
||||
--column;
|
||||
#else
|
||||
unsigned column = 0;
|
||||
#endif
|
||||
|
||||
return openCppEditorAt(fileName, s->line(), column);
|
||||
}
|
||||
|
||||
@@ -815,14 +815,17 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
|
||||
warningFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
|
||||
warningFormat.setUnderlineColor(Qt::darkYellow);
|
||||
|
||||
QSet<int> lines;
|
||||
QSet<QPair<unsigned, unsigned> > lines;
|
||||
foreach (const Document::DiagnosticMessage &m, doc->diagnosticMessages()) {
|
||||
if (m.fileName() != fileName)
|
||||
continue;
|
||||
else if (lines.contains(m.line()))
|
||||
|
||||
const QPair<unsigned, unsigned> coordinates = qMakePair(m.line(), m.column());
|
||||
|
||||
if (lines.contains(coordinates))
|
||||
continue;
|
||||
|
||||
lines.insert(m.line());
|
||||
lines.insert(coordinates);
|
||||
|
||||
QTextEdit::ExtraSelection sel;
|
||||
if (m.isWarning())
|
||||
@@ -831,14 +834,28 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
|
||||
sel.format = errorFormat;
|
||||
|
||||
QTextCursor c(ed->document()->findBlockByNumber(m.line() - 1));
|
||||
const QString text = c.block().text();
|
||||
for (int i = 0; i < text.size(); ++i) {
|
||||
if (! text.at(i).isSpace()) {
|
||||
c.setPosition(c.position() + i);
|
||||
break;
|
||||
|
||||
// ### check for generated tokens.
|
||||
|
||||
int column = m.column();
|
||||
|
||||
if (column > c.block().length()) {
|
||||
column = 0;
|
||||
|
||||
const QString text = c.block().text();
|
||||
for (int i = 0; i < text.size(); ++i) {
|
||||
if (! text.at(i).isSpace()) {
|
||||
++column;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
|
||||
if (column != 0)
|
||||
--column;
|
||||
|
||||
c.setPosition(c.position() + column);
|
||||
c.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
||||
sel.cursor = c;
|
||||
selections.append(sel);
|
||||
}
|
||||
|
||||
@@ -134,10 +134,15 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
||||
|
||||
if (! ast->declarators && ast->decl_specifier_seq && ! ast->decl_specifier_seq->next) {
|
||||
if (ElaboratedTypeSpecifierAST *elab_type_spec = ast->decl_specifier_seq->asElaboratedTypeSpecifier()) {
|
||||
|
||||
unsigned sourceLocation = elab_type_spec->firstToken();
|
||||
|
||||
if (elab_type_spec->name)
|
||||
sourceLocation = elab_type_spec->name->firstToken();
|
||||
|
||||
Name *name = semantic()->check(elab_type_spec->name, _scope);
|
||||
ForwardClassDeclaration *symbol =
|
||||
control()->newForwardClassDeclaration(elab_type_spec->firstToken(),
|
||||
name);
|
||||
control()->newForwardClassDeclaration(sourceLocation, name);
|
||||
|
||||
if (_templateParameters) {
|
||||
symbol->setTemplateParameters(_templateParameters);
|
||||
@@ -155,8 +160,15 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
||||
FullySpecifiedType declTy = semantic()->check(it->declarator, qualTy,
|
||||
_scope, &name);
|
||||
|
||||
unsigned location = 0;
|
||||
if (it->declarator)
|
||||
location = it->declarator->firstToken();
|
||||
else
|
||||
location = ast->firstToken();
|
||||
|
||||
Function *fun = 0;
|
||||
if (declTy && 0 != (fun = declTy->asFunctionType())) {
|
||||
fun->setSourceLocation(location);
|
||||
fun->setScope(_scope);
|
||||
fun->setName(name);
|
||||
fun->setMethodKey(semantic()->currentMethodKey());
|
||||
@@ -166,12 +178,6 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
||||
"expected a function declaration");
|
||||
}
|
||||
|
||||
unsigned location = 0;
|
||||
if (it->declarator)
|
||||
location = it->declarator->firstToken();
|
||||
else
|
||||
location = ast->firstToken();
|
||||
|
||||
Declaration *symbol = control()->newDeclaration(location, name);
|
||||
symbol->setType(control()->integerType(IntegerType::Int));
|
||||
symbol->setType(declTy);
|
||||
@@ -246,6 +252,8 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast)
|
||||
}
|
||||
|
||||
Function *fun = funTy->asFunctionType();
|
||||
if (ast->declarator)
|
||||
fun->setSourceLocation(ast->declarator->firstToken());
|
||||
fun->setName(name);
|
||||
fun->setTemplateParameters(_templateParameters);
|
||||
fun->setVisibility(semantic()->currentVisibility());
|
||||
@@ -305,7 +313,13 @@ bool CheckDeclaration::visit(NamespaceAST *ast)
|
||||
{
|
||||
Identifier *id = identifier(ast->identifier_token);
|
||||
Name *namespaceName = control()->nameId(id);
|
||||
Namespace *ns = control()->newNamespace(ast->firstToken(), namespaceName);
|
||||
|
||||
unsigned sourceLocation = ast->firstToken();
|
||||
|
||||
if (ast->identifier_token)
|
||||
sourceLocation = ast->identifier_token;
|
||||
|
||||
Namespace *ns = control()->newNamespace(sourceLocation, namespaceName);
|
||||
ast->symbol = ns;
|
||||
_scope->enterSymbol(ns);
|
||||
semantic()->check(ast->linkage_body, ns->members()); // ### we'll do the merge later.
|
||||
@@ -325,12 +339,17 @@ bool CheckDeclaration::visit(NamespaceAliasDefinitionAST *)
|
||||
|
||||
bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
|
||||
{
|
||||
unsigned sourceLocation = 0;
|
||||
|
||||
if (ast->declarator)
|
||||
sourceLocation = ast->declarator->firstToken();
|
||||
|
||||
Name *argName = 0;
|
||||
FullySpecifiedType ty = semantic()->check(ast->type_specifier, _scope);
|
||||
FullySpecifiedType argTy = semantic()->check(ast->declarator, ty.qualifiedType(),
|
||||
_scope, &argName);
|
||||
FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
|
||||
Argument *arg = control()->newArgument(ast->firstToken(), argName);
|
||||
Argument *arg = control()->newArgument(sourceLocation, argName);
|
||||
ast->symbol = arg;
|
||||
if (ast->expression)
|
||||
arg->setInitializer(true);
|
||||
@@ -354,8 +373,12 @@ bool CheckDeclaration::visit(TemplateDeclarationAST *ast)
|
||||
|
||||
bool CheckDeclaration::visit(TypenameTypeParameterAST *ast)
|
||||
{
|
||||
unsigned sourceLocation = ast->firstToken();
|
||||
if (ast->name)
|
||||
sourceLocation = ast->name->firstToken();
|
||||
|
||||
Name *name = semantic()->check(ast->name, _scope);
|
||||
Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type
|
||||
Argument *arg = control()->newArgument(sourceLocation, name); // ### new template type
|
||||
ast->symbol = arg;
|
||||
_scope->enterSymbol(arg);
|
||||
return false;
|
||||
@@ -363,8 +386,12 @@ bool CheckDeclaration::visit(TypenameTypeParameterAST *ast)
|
||||
|
||||
bool CheckDeclaration::visit(TemplateTypeParameterAST *ast)
|
||||
{
|
||||
unsigned sourceLocation = ast->firstToken();
|
||||
if (ast->name)
|
||||
sourceLocation = ast->name->firstToken();
|
||||
|
||||
Name *name = semantic()->check(ast->name, _scope);
|
||||
Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type
|
||||
Argument *arg = control()->newArgument(sourceLocation, name); // ### new template type
|
||||
ast->symbol = arg;
|
||||
_scope->enterSymbol(arg);
|
||||
return false;
|
||||
@@ -373,7 +400,12 @@ bool CheckDeclaration::visit(TemplateTypeParameterAST *ast)
|
||||
bool CheckDeclaration::visit(UsingAST *ast)
|
||||
{
|
||||
Name *name = semantic()->check(ast->name, _scope);
|
||||
UsingDeclaration *u = control()->newUsingDeclaration(ast->firstToken(), name);
|
||||
|
||||
unsigned sourceLocation = ast->firstToken();
|
||||
if (ast->name)
|
||||
sourceLocation = ast->name->firstToken();
|
||||
|
||||
UsingDeclaration *u = control()->newUsingDeclaration(sourceLocation, name);
|
||||
ast->symbol = u;
|
||||
_scope->enterSymbol(u);
|
||||
return false;
|
||||
@@ -382,7 +414,12 @@ bool CheckDeclaration::visit(UsingAST *ast)
|
||||
bool CheckDeclaration::visit(UsingDirectiveAST *ast)
|
||||
{
|
||||
Name *name = semantic()->check(ast->name, _scope);
|
||||
UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(ast->firstToken(), name);
|
||||
|
||||
unsigned sourceLocation = ast->firstToken();
|
||||
if (ast->name)
|
||||
sourceLocation = ast->name->firstToken();
|
||||
|
||||
UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(sourceLocation, name);
|
||||
ast->symbol = u;
|
||||
_scope->enterSymbol(u);
|
||||
|
||||
|
||||
@@ -296,8 +296,13 @@ bool CheckSpecifier::visit(SimpleSpecifierAST *ast)
|
||||
|
||||
bool CheckSpecifier::visit(ClassSpecifierAST *ast)
|
||||
{
|
||||
unsigned sourceLocation = ast->firstToken();
|
||||
|
||||
if (ast->name)
|
||||
sourceLocation = ast->name->firstToken();
|
||||
|
||||
Name *className = semantic()->check(ast->name, _scope);
|
||||
Class *klass = control()->newClass(ast->firstToken(), className);
|
||||
Class *klass = control()->newClass(sourceLocation, className);
|
||||
ast->symbol = klass;
|
||||
unsigned classKey = tokenKind(ast->classkey_token);
|
||||
if (classKey == T_CLASS)
|
||||
@@ -358,8 +363,12 @@ bool CheckSpecifier::visit(ElaboratedTypeSpecifierAST *ast)
|
||||
|
||||
bool CheckSpecifier::visit(EnumSpecifierAST *ast)
|
||||
{
|
||||
unsigned sourceLocation = ast->firstToken();
|
||||
if (ast->name)
|
||||
sourceLocation = ast->name->firstToken();
|
||||
|
||||
Name *name = semantic()->check(ast->name, _scope);
|
||||
Enum *e = control()->newEnum(ast->firstToken(), name);
|
||||
Enum *e = control()->newEnum(sourceLocation, name);
|
||||
e->setVisibility(semantic()->currentVisibility());
|
||||
_scope->enterSymbol(e);
|
||||
_fullySpecifiedType.setType(e);
|
||||
|
||||
@@ -166,9 +166,7 @@ Symbol::Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *
|
||||
_index(0),
|
||||
_next(0)
|
||||
{
|
||||
if (sourceLocation)
|
||||
_sourceOffset = translationUnit->tokenAt(sourceLocation).offset;
|
||||
|
||||
setSourceLocation(sourceLocation);
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@@ -202,6 +200,16 @@ unsigned Symbol::sourceLocation() const
|
||||
unsigned Symbol::sourceOffset() const
|
||||
{ return _sourceOffset; }
|
||||
|
||||
void Symbol::setSourceLocation(unsigned sourceLocation)
|
||||
{
|
||||
_sourceLocation = sourceLocation;
|
||||
|
||||
if (_sourceLocation)
|
||||
_sourceOffset = translationUnit()->tokenAt(sourceLocation).offset;
|
||||
else
|
||||
_sourceOffset = 0;
|
||||
}
|
||||
|
||||
unsigned Symbol::line() const
|
||||
{
|
||||
unsigned line = 0, column = 0;
|
||||
@@ -212,14 +220,10 @@ unsigned Symbol::line() const
|
||||
|
||||
unsigned Symbol::column() const
|
||||
{
|
||||
#ifdef CPLUSPLUS_WITH_COLUMNS
|
||||
unsigned line = 0, column = 0;
|
||||
StringLiteral *fileId = 0;
|
||||
translationUnit()->getPosition(_sourceOffset, &line, &column, &fileId);
|
||||
return column;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
StringLiteral *Symbol::fileId() const
|
||||
|
||||
@@ -234,6 +234,7 @@ public:
|
||||
Name *identity() const;
|
||||
|
||||
void setScope(Scope *scope); // ### make me private
|
||||
void setSourceLocation(unsigned sourceLocation); // ### make me private
|
||||
|
||||
void visitSymbol(SymbolVisitor *visitor);
|
||||
static void visitSymbol(Symbol *symbol, SymbolVisitor *visitor);
|
||||
|
||||
Reference in New Issue
Block a user