156
144
return new CodeHighlightingInstance(this);
159
void CodeHighlighting::highlightDUChain(TopDUContext* context) const
161
kDebug() << "highlighting du chain" << context->url().toUrl();
163
DUChainReadLocker lock(DUChain::lock());
147
bool CodeHighlighting::hasHighlighting(IndexedString url) const
149
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(url);
152
QMutexLocker lock(&m_dataMutex);
153
return m_highlights.contains(tracker) && !m_highlights[tracker]->m_highlightedRanges.isEmpty();
158
void CodeHighlighting::highlightDUChain(ReferencedTopDUContext context)
163
DUChainReadLocker lock;
164
url = context->url();
167
// This prevents the background-parser from updating the top-context while we're working with it
168
UrlParseLock urlLock(context->url());
170
DUChainReadLocker lock;
172
qint64 revision = context->parsingEnvironmentFile()->modificationRevision().revision;
174
kDebug() << "highlighting du chain" << url.toUrl();
165
176
if ( !m_localColorization && !m_globalColorization ) {
166
177
kDebug() << "highlighting disabled";
167
deleteHighlighting(context);
178
QMetaObject::invokeMethod(this, "clearHighlightingForDocument", Qt::QueuedConnection, Q_ARG(KDevelop::IndexedString, url));
171
182
CodeHighlightingInstance* instance = createInstance();
173
instance->highlightDUChain(context);
186
instance->highlightDUChain(context.data());
188
DocumentHighlighting* highlighting = new DocumentHighlighting;
189
highlighting->m_document = url;
190
highlighting->m_waitingRevision = revision;
191
highlighting->m_waiting = instance->m_highlight;
192
qSort(highlighting->m_waiting.begin(), highlighting->m_waiting.end());
194
QMetaObject::invokeMethod(this, "applyHighlighting", Qt::QueuedConnection, Q_ARG(void*, highlighting));
178
void CodeHighlighting::deleteHighlighting(KDevelop::DUContext* context) const {
179
if (!context->smartRange())
183
LOCK_SMART(context->smartRange());
185
foreach (Declaration* dec, context->localDeclarations())
186
if(dec->smartRange() && isCodeHighlight(dec->smartRange()->attribute()))
187
dec->smartRange()->setAttribute(KTextEditor::Attribute::Ptr());
189
for(int a = 0; a < context->usesCount(); ++a)
190
if(context->useSmartRange(a) && isCodeHighlight(context->useSmartRange(a)->attribute()))
191
context->useSmartRange(a)->setAttribute(KTextEditor::Attribute::Ptr());
194
foreach (DUContext* child, context->childContexts())
195
deleteHighlighting(child);
198
void CodeHighlightingInstance::highlightDUChain(DUContext* context) const
199
void CodeHighlightingInstance::highlightDUChain(TopDUContext* context)
200
201
m_contextClasses.clear();
201
202
m_useClassCache = true;
204
highlightDUChainSimple(static_cast<DUContext*>(context));
205
highlightDUChain(context, QHash<Declaration*, uint>(), emptyColorMap());
206
207
m_functionColorsForDeclarations.clear();
207
208
m_functionDeclarationsForColors.clear();
439
void CodeHighlightingInstance::highlightDeclaration(Declaration * declaration, const QColor &color) const
441
if (SmartRange* range = declaration->smartRange()) {
444
if(!m_highlighting->isCodeHighlight(range->attribute()))
447
range->setAttribute(m_highlighting->attributeForType(typeForDeclaration(declaration, 0), DeclarationContext, color));
451
void CodeHighlightingInstance::highlightUse(DUContext* context, int index, const QColor &color) const
453
if (SmartRange* range = context->useSmartRange(index)) {
455
Types type = ErrorVariableType;
456
Declaration* decl = context->topContext()->usedDeclarationForIndex(context->uses()[index].m_declarationIndex);
458
type = typeForDeclaration(decl, context);
462
if(!m_highlighting->isCodeHighlight(range->attribute())) {
466
if(type != ErrorVariableType || ICore::self()->languageController()->completionSettings()->highlightSemanticProblems())
467
range->setAttribute(m_highlighting->attributeForType(type, ReferenceContext, color));
420
bool CodeHighlightingInstance::useRainbowColor(Declaration* dec) const
422
return dec->context()->type() == DUContext::Function || (dec->context()->type() == DUContext::Other && dec->context()->owner());
425
void CodeHighlightingInstance::highlightDeclaration(Declaration * declaration, const QColor &color)
428
h.range = declaration->range();
429
h.attribute = m_highlighting->attributeForType(typeForDeclaration(declaration, 0), DeclarationContext, color);
430
m_highlight.push_back(h);
433
void CodeHighlightingInstance::highlightUse(DUContext* context, int index, const QColor &color)
435
Types type = ErrorVariableType;
436
Declaration* decl = context->topContext()->usedDeclarationForIndex(context->uses()[index].m_declarationIndex);
438
type = typeForDeclaration(decl, context);
440
if(type != ErrorVariableType || ICore::self()->languageController()->completionSettings()->highlightSemanticProblems())
443
h.range = context->uses()[index].m_range;
444
h.attribute = m_highlighting->attributeForType(type, ReferenceContext, color);
445
m_highlight.push_back(h);
449
void CodeHighlightingInstance::highlightUses(DUContext* context)
451
for(int a = 0; a < context->usesCount(); ++a)
452
highlightUse(context, a, QColor(QColor::Invalid));
456
void CodeHighlighting::clearHighlightingForDocument(IndexedString document)
458
VERIFY_FOREGROUND_LOCKED
459
QMutexLocker lock(&m_dataMutex);
460
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(document);
461
if(m_highlights.contains(tracker))
463
disconnect(tracker, SIGNAL(destroyed(QObject*)), this, SLOT(trackerDestroyed(QObject*)));
464
qDeleteAll(m_highlights[tracker]->m_highlightedRanges);
465
delete m_highlights[tracker];
466
m_highlights.remove(tracker);
470
void CodeHighlighting::applyHighlighting(void* _highlighting)
472
CodeHighlighting::DocumentHighlighting* highlighting = static_cast<CodeHighlighting::DocumentHighlighting*>(_highlighting);
474
VERIFY_FOREGROUND_LOCKED
475
QMutexLocker lock(&m_dataMutex);
476
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(highlighting->m_document);
480
kDebug() << "no document found for the planned highlighting of" << highlighting->m_document.str();
485
QVector< MovingRange* > oldHighlightedRanges;
487
if(m_highlights.contains(tracker))
489
oldHighlightedRanges = m_highlights[tracker]->m_highlightedRanges;
490
delete m_highlights[tracker];
492
// we newly add this tracker, so add the connection
493
connect(tracker, SIGNAL(destroyed(QObject*)), SLOT(trackerDestroyed(QObject*)));
494
connect(tracker->document(), SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*)),
495
this, SLOT(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*)));
496
connect(tracker->document(), SIGNAL(aboutToRemoveText(KTextEditor::Range)),
497
this, SLOT(aboutToRemoveText(KTextEditor::Range)));
500
m_highlights[tracker] = highlighting;
502
// Now create MovingRanges (match old ones with the incoming ranges)
504
KTextEditor::Range tempRange;
506
QVector<MovingRange*>::iterator movingIt = oldHighlightedRanges.begin();
507
QVector<HighlightedRange>::iterator rangeIt = highlighting->m_waiting.begin();
509
while(rangeIt != highlighting->m_waiting.end())
511
// Translate the range into the current revision
512
SimpleRange transformedRange = tracker->transformToCurrentRevision(rangeIt->range, highlighting->m_waitingRevision);
514
while(movingIt != oldHighlightedRanges.end() &&
515
((*movingIt)->start().line() < transformedRange.start.line ||
516
((*movingIt)->start().line() == transformedRange.start.line && (*movingIt)->start().column() < transformedRange.start.column)))
518
delete *movingIt; // Skip ranges that are in front of the current matched range
522
tempRange.start().setPosition(transformedRange.start.line, transformedRange.start.column);
523
tempRange.end().setPosition(transformedRange.end.line, transformedRange.end.column);
525
if(movingIt == oldHighlightedRanges.end() ||
526
transformedRange.start.line != (*movingIt)->start().line() ||
527
transformedRange.start.column != (*movingIt)->start().column() ||
528
transformedRange.end.line != (*movingIt)->end().line() ||
529
transformedRange.end.column != (*movingIt)->end().column())
531
Q_ASSERT(rangeIt->attribute);
532
// The moving range is behind or unequal, create a new range
533
highlighting->m_highlightedRanges.push_back(tracker->documentMovingInterface()->newMovingRange(tempRange));
534
highlighting->m_highlightedRanges.back()->setAttribute(rangeIt->attribute);
535
highlighting->m_highlightedRanges.back()->setZDepth(highlightingZDepth);
469
range->setAttribute(KTextEditor::Attribute::Ptr());
539
// Update the existing moving range
540
(*movingIt)->setAttribute(rangeIt->attribute);
541
(*movingIt)->setRange(tempRange);
542
highlighting->m_highlightedRanges.push_back(*movingIt);
473
void CodeHighlightingInstance::highlightUses(DUContext* context) const
475
for(int a = 0; a < context->usesCount(); ++a) {
476
highlightUse(context, a, QColor(QColor::Invalid));
548
for(; movingIt != oldHighlightedRanges.end(); ++movingIt)
549
delete *movingIt; // Delete unmatched moving ranges behind
552
void CodeHighlighting::trackerDestroyed(QObject* object)
554
// Called when a document is destroyed
555
VERIFY_FOREGROUND_LOCKED
556
QMutexLocker lock(&m_dataMutex);
557
DocumentChangeTracker* tracker = static_cast<DocumentChangeTracker*>(object);
558
Q_ASSERT(m_highlights.contains(tracker));
559
delete m_highlights[tracker]; // No need to care about the individual ranges, as the document is being destroyed
560
m_highlights.remove(tracker);
563
void CodeHighlighting::aboutToInvalidateMovingInterfaceContent(Document* doc)
565
clearHighlightingForDocument(IndexedString(doc->url()));
568
void CodeHighlighting::aboutToRemoveText( const KTextEditor::Range& range )
570
if (range.onSingleLine()) // don't try to optimize this
573
VERIFY_FOREGROUND_LOCKED
574
QMutexLocker lock(&m_dataMutex);
575
Q_ASSERT(dynamic_cast<KTextEditor::Document*>(sender()));
576
KTextEditor::Document* doc = static_cast<KTextEditor::Document*>(sender());
578
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()
579
->trackerForUrl(IndexedString(doc->url()));
580
if(m_highlights.contains(tracker))
582
QVector<MovingRange*>& ranges = m_highlights.value(tracker)->m_highlightedRanges;
583
QVector<MovingRange*>::iterator it = ranges.begin();
584
while(it != ranges.end()) {
585
if (range.contains((*it)->toRange())) {
587
it = ranges.erase(it);