예제 #1
0
void RangeTest::rangeCheck(KTextEditor::Range &valid)
{
    QVERIFY(valid.isValid() && valid.start() <= valid.end());

    KTextEditor::Cursor before(0, 1), start(0, 2), end(1, 4), after(1, 10);

    KTextEditor::Range result(start, end);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());

    valid.setRange(start, end);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, result);

    valid.setRange(end, start);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, result);

    valid.setStart(after);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, KTextEditor::Range(after, after));

    valid = result;
    QCOMPARE(valid, result);

    valid.setEnd(before);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, KTextEditor::Range(before, before));
}
void AdaptSignatureAssistant::textChanged(KTextEditor::View* view, const KTextEditor::Range& invocationRange, const QString& removedText)
{
  reset();

  m_view = view;

  //FIXME: update signature assistant to play well with the rename assistant
  KTextEditor::Range sigAssistRange = invocationRange;
  if (!removedText.isEmpty()) {
    sigAssistRange.setRange(sigAssistRange.start(), sigAssistRange.start());
  }

  m_document = view->document()->url();

  DUChainReadLocker lock(DUChain::lock(), 300);
  if(!lock.locked()) {
    qCDebug(CPP) << "failed to lock duchain in time";
    return;
  }

  KTextEditor::Range simpleInvocationRange = KTextEditor::Range(sigAssistRange);
  Declaration* funDecl = getDeclarationAtCursor(simpleInvocationRange.start(), m_document);
  if(!funDecl || !funDecl->type<FunctionType>())
    return;

  if(QtFunctionDeclaration* classFun = dynamic_cast<QtFunctionDeclaration*>(funDecl)) {
    if (classFun->isSignal()) {
      // do not offer to change signature of a signal, as the implementation will be generated by moc
      return;
    }
  }

  Declaration* otherSide = 0;
  FunctionDefinition* definition = dynamic_cast<FunctionDefinition*>(funDecl);
  if (definition)
  {
    m_editingDefinition = true;
    otherSide = definition->declaration();
  }
  else if ((definition = FunctionDefinition::definition(funDecl)))
  {
    m_editingDefinition = false;
    otherSide = definition;
  }

  if (!otherSide)
    return;

  m_otherSideContext = DUContextPointer(DUChainUtils::getFunctionContext(otherSide));
  if (!m_otherSideContext)
    return;

  m_declarationName = funDecl->identifier();
  m_otherSideId = otherSide->id();
  m_otherSideTopContext = ReferencedTopDUContext(otherSide->topContext());
  m_oldSignature = getDeclarationSignature(otherSide, m_otherSideContext.data(), true);

  //Schedule an update, to make sure the ranges match
  DUChain::self()->updateContextForUrl(m_otherSideTopContext->url(), TopDUContext::AllDeclarationsAndContexts);
}
예제 #3
0
void TextHistory::transformRange(KTextEditor::Range &range, KTextEditor::MovingRange::InsertBehaviors insertBehaviors, KTextEditor::MovingRange::EmptyBehavior emptyBehavior, qint64 fromRevision, qint64 toRevision)
{
    /**
     * invalidate on empty?
     */
    bool invalidateIfEmpty = emptyBehavior == KTextEditor::MovingRange::InvalidateIfEmpty;
    if (invalidateIfEmpty && range.end() <= range.start()) {
        range = KTextEditor::Range::invalid();
        return;
    }

    /**
     * -1 special meaning for from/toRevision
     */
    if (fromRevision == -1) {
        fromRevision = revision();
    }

    if (toRevision == -1) {
        toRevision = revision();
    }

    /**
     * shortcut, same revision
     */
    if (fromRevision == toRevision) {
        return;
    }

    /**
     * some invariants must hold
     */
    Q_ASSERT(!m_historyEntries.empty());
    Q_ASSERT(fromRevision != toRevision);
    Q_ASSERT(fromRevision >= m_firstHistoryEntryRevision);
    Q_ASSERT(fromRevision < (m_firstHistoryEntryRevision + m_historyEntries.size()));
    Q_ASSERT(toRevision >= m_firstHistoryEntryRevision);
    Q_ASSERT(toRevision < (m_firstHistoryEntryRevision + m_historyEntries.size()));

    /**
     * transform cursors
     */

    // first: copy cursors, without range association
    int startLine = range.start().line(), startColumn = range.start().column(), endLine = range.end().line(), endColumn = range.end().column();

    bool moveOnInsertStart = !(insertBehaviors & KTextEditor::MovingRange::ExpandLeft);
    bool moveOnInsertEnd = (insertBehaviors & KTextEditor::MovingRange::ExpandRight);

    /**
     * forward or reverse transform?
     */
    if (toRevision > fromRevision) {
        for (int rev = fromRevision - m_firstHistoryEntryRevision + 1; rev <= (toRevision - m_firstHistoryEntryRevision); ++rev) {
            const Entry &entry = m_historyEntries.at(rev);

            entry.transformCursor(startLine, startColumn, moveOnInsertStart);

            entry.transformCursor(endLine, endColumn, moveOnInsertEnd);

            // got empty?
            if (endLine < startLine || (endLine == startLine && endColumn <= startColumn)) {
                if (invalidateIfEmpty) {
                    range = KTextEditor::Range::invalid();
                    return;
                } else {
                    // else normalize them
                    endLine = startLine;
                    endColumn = startColumn;
                }
            }
        }
    } else {
        for (int rev = fromRevision - m_firstHistoryEntryRevision; rev >= (toRevision - m_firstHistoryEntryRevision + 1); --rev) {
            const Entry &entry = m_historyEntries.at(rev);

            entry.reverseTransformCursor(startLine, startColumn, moveOnInsertStart);

            entry.reverseTransformCursor(endLine, endColumn, moveOnInsertEnd);

            // got empty?
            if (endLine < startLine || (endLine == startLine && endColumn <= startColumn)) {
                if (invalidateIfEmpty) {
                    range = KTextEditor::Range::invalid();
                    return;
                } else {
                    // else normalize them
                    endLine = startLine;
                    endColumn = startColumn;
                }
            }
        }
    }

    // now, copy cursors back
    range.setRange(KTextEditor::Cursor(startLine, startColumn), KTextEditor::Cursor(endLine, endColumn));
}