Esempio n. 1
0
/** Conversion function from QtScript range to KTextEditor::Range */
static void rangeFromScriptValue(const QScriptValue &obj, KTextEditor::Range &range)
{
  range.start().setPosition(obj.property("start").property("line").toInt32(),
                            obj.property("start").property("column").toInt32());
  range.end().setPosition(obj.property("end").property("line").toInt32(),
                          obj.property("end").property("column").toInt32());
}
Esempio n. 2
0
QRect KTextEditorHelpers::getItemBoundingRect(const KTextEditor::View* view, const KTextEditor::Range& itemRange)
{
  QPoint startPoint = view->mapToGlobal(view->cursorToCoordinate(itemRange.start()));
  QPoint endPoint = view->mapToGlobal(view->cursorToCoordinate(itemRange.end()));
  endPoint.ry() += getLineHeight(view, itemRange.start().line());
  return QRect(startPoint, endPoint);
}
Esempio n. 3
0
/** Conversion function from QtScript range to KTextEditor::Range */
static QScriptValue rangeToScriptValue(QScriptEngine *engine, const KTextEditor::Range &range)
{
  QString code = QString("new Range(%1, %2, %3, %4);").arg(range.start().line())
                                                      .arg(range.start().column())
                                                      .arg(range.end().line())
                                                      .arg(range.end().column());
  return engine->evaluate(code);
}
void ClangCodeCompletionModel::executeCompletionItem2(
    KTextEditor::Document* const doc
  , const KTextEditor::Range& word
  , const QModelIndex& index
  ) const
{
    assert("Active view expected to be equal to the stored one" && doc->activeView() == m_current_view);
    assert("Invalid index is not expected here!" && index.isValid());
    assert("Parent index is not valid" && index.parent().isValid());
    assert("Parent index must be GROUP" && index.parent().internalId() == Level::GROUP);
    assert(
        "Parent index points to invalid group"
      && 0 <= index.internalId()
      && unsigned(index.internalId()) < m_groups.size()
      );
    assert(
        "Index points to invalid item"
      && 0 <= index.row()
      && unsigned(index.row()) < m_groups[index.internalId()].second.m_completions.size()
      );

    auto* const template_iface = qobject_cast<KTextEditor::TemplateInterface2*>(m_current_view);
    if (template_iface)
    {
        kDebug(DEBUG_AREA) << "TemplateInterface available for a view" << m_current_view;
        const auto result = m_groups[index.internalId()]
          .second.m_completions[index.row()]
          .getCompletionTemplate();
        kDebug(DEBUG_AREA) << "Template:" << result.m_tpl;
        kDebug(DEBUG_AREA) << "Values:" << result.m_values;
        // Check if current template is a function and there is a '()' right after cursor
        auto range = word;
        if (result.m_is_function)
        {
            const auto next_word_range = DocumentProxy(doc).firstWordAfterCursor(word.end());
            kDebug(DEBUG_AREA) << "OK THIS IS FUNCTION TEMPLATE: next word range" << next_word_range;
            kDebug(DEBUG_AREA) << "replace range before:" << range;
            if (next_word_range.isValid() && doc->text(next_word_range).startsWith(QLatin1String("()")))
            {
                range.end().setColumn(next_word_range.start().column() + 2);
                kDebug(DEBUG_AREA) << "replace range after:" << range;
            }
        }
        doc->removeText(range);
        template_iface->insertTemplateText(range.start(), result.m_tpl, result.m_values, nullptr);
    }
    else
    {
        kDebug(DEBUG_AREA) << "No TemplateInterface for a view" << m_current_view;
        const auto p = m_groups[index.internalId()].second.m_completions[index.row()].executeCompletion();
        doc->replaceText(word, p.first);
        // Try to reposition a cursor inside a current (hope it still is) view
        auto pos = word.start();
        pos.setColumn(pos.column() + p.second);
        m_current_view->setCursorPosition(pos);
    }
}
Esempio n. 5
0
void CodeCompletionWorker::updateContextRange(KTextEditor::Range& contextRange, KTextEditor::View* /*view*/, DUContextPointer context) const
{
  if(context && context->owner() && context->owner()->type<FunctionType>()) {
    if(!context->owner()->type<FunctionType>()->returnType()) {
      //For constructor completion, we need some more context
      contextRange.start().setLine(contextRange.start().line() > 30 ? contextRange.start().line()-30 : 0);
      contextRange.start().setColumn(0);
    }
  }
}
Esempio n. 6
0
// Scan throughout the entire document for possible completions,
// ignoring any dublets
const QStringList KateWordCompletionModel::allMatches( KTextEditor::View *view, const KTextEditor::Range &range ) const
{
  KTextEditor::Document *doc = view->document();
  QString match_str = doc->text(range);
  QString s, m;
  QSet<QString> seen;
  QStringList l;

  int i( 0 );
  int pos( 0 );

  QRegExp re( "\\b(" + match_str + "\\w{1,})" );

  while( i < doc->lines() )
  {
      s = doc->line( i );
      pos = 0;
      while ( pos >= 0 )
      {
        pos = re.indexIn( s, pos );
        if ( pos >= 0 )
        {
          // typing in the middle of a word
          if ( ! ( i == range.start().line() && pos == range.start().column() ) )
          {
            m = re.cap( 1 );
            if ( ! seen.contains( m ) ) {
              seen.insert( m );
              l << m;
            }
          }
          pos += re.matchedLength();
        }
      }
    i++;
  }

  // Global completion
  // int db_area = KDebug::registerArea("ktuan-debug");
  QMap<QString, QStringList>::const_iterator ci = doc_word_list.constBegin();
  while (ci != doc_word_list.constEnd()) {
  if (ci.key() != doc->url().prettyUrl()) {
    QStringList list = ci.value();
    foreach (QString word, list) {
      // kDebug(db_area) << "complete word " << word;
      if (word.startsWith(match_str) && !seen.contains(word)) {
        // kDebug(db_area) << "Global completion";
        seen.insert(word);
        l << word;
      }
    }
  }
  ++ci;
  }
Esempio n. 7
0
void TextHistory::removeText(const KTextEditor::Range &range, int oldLineLength)
{
    // create and add new entry
    Entry entry;
    entry.type = Entry::RemoveText;
    entry.line = range.start().line();
    entry.column = range.start().column();
    entry.length = range.end().column() - range.start().column();
    entry.oldLineLength = oldLineLength;
    addEntry(entry);
}
void ImplementFunctionCompletionItem::execute(KTextEditor::Document* document, const KTextEditor::Range& word)
{
    const QString finalText = m_name + "(" + m_arguments.join(", ") + "):";
    document->replaceText(word, finalText);
    // 4 spaces is indentation for python. everyone does it like this. you must, too.
    // TODO use kate settings
    document->insertLine(word.start().line() + 1, m_previousIndent + "    ");
    if ( View* view = document->activeView() ) {
        view->setCursorPosition(Cursor(word.end().line() + 1, m_previousIndent.length() + 4));
    }
}
Esempio n. 9
0
void LaTeXInfo::startLaTeXCompletion(KTextEditor::View *view)
{
	KTextEditor::CodeCompletionInterface* completionInterface = qobject_cast<KTextEditor::CodeCompletionInterface*>(view);
	if(!completionInterface) {
		return;
	}
	KTextEditor::Range range = m_latexCompletionModel->completionRange(view, view->cursorPosition());
	if(!range.isValid()) {
		range = KTextEditor::Range(view->cursorPosition(), view->cursorPosition());
	}
	completionInterface->startCompletion(range, m_latexCompletionModel);
}
Esempio n. 10
0
void KeywordItem::execute(KTextEditor::View* view, const KTextEditor::Range& word)
{
    KTextEditor::Document *document = view->document();
    if ( !m_replacement.isEmpty() ) {
        QString replacement = m_replacement;
        replacement = replacement.replace('\n', '\n' + getIndendation(document->line(word.start().line())));
        replacement = replacement.replace(QLatin1String("%INDENT%"), indentString(document));

        int cursorPos = replacement.indexOf(QStringLiteral("%CURSOR%"));
        int selectionEnd = -1;
        if ( cursorPos != -1 ) {
            replacement.remove(QStringLiteral("%CURSOR%"));
        } else {
            cursorPos = replacement.indexOf(QStringLiteral("%SELECT%"));
            if ( cursorPos != -1 ) {
                replacement.remove(QStringLiteral("%SELECT%"));
                selectionEnd = replacement.indexOf(QStringLiteral("%ENDSELECT%"), cursorPos + 1);
                if ( selectionEnd == -1 ) {
                    selectionEnd = replacement.length();
                }
                replacement.remove(QStringLiteral("%ENDSELECT%"));
            }
        }

        document->replaceText(word, replacement);

        if ( cursorPos != -1 ) {
            if (view) {
                replacement = replacement.left(cursorPos);
                KTextEditor::Cursor newPos(
                    word.start().line() + replacement.count('\n'),
                    word.start().column() + replacement.length() - replacement.lastIndexOf('\n') - 1
                );
                view->setCursorPosition(newPos);
                if ( selectionEnd != -1 ) {
                    ///TODO: maybe we want to support multi-line selections in the future?
                    view->setSelection(
                        KTextEditor::Range(
                            newPos,
                            KTextEditor::Cursor(
                                newPos.line(),
                                newPos.column() + selectionEnd - cursorPos
                            )
                        )
                    );
                }
            }
        }
    } else {
        document->replaceText(word, m_keyword + ' ');
    }
}
Esempio n. 11
0
void SwapFile::removeText (const KTextEditor::Range &range)
{
  // skip if not open
  if (!m_swapfile.isOpen ())
    return;
  
  // format: qint8, int, int, int
  Q_ASSERT (range.start().line() == range.end().line());
  m_stream << EA_RemoveText
            << range.start().line() << range.start().column()
            << range.end().column();

  m_needSync = true;
}
Esempio n. 12
0
void KDocumentTextBuffer::localTextRemoved( KTextEditor::Document *document,
    const KTextEditor::Range &range, const QString& oldText )
{
    if ( m_aboutToClose ) return;

    kDebug() << "local text removed:" << kDocument() << range;
    emit localChangedText(range, user(), true);

    Q_UNUSED(document)

    textOpPerformed();
    if( !m_user.isNull() )
    {
        unsigned int offset = cursorToOffset_kte( range.start() );
        unsigned int len = countUnicodeCharacters(oldText);
        blockRemoteRemove = true;
        kDebug() << "ERASING TEXT" << oldText << "with len" << len << "offset" << offset << "range" << range;
        kDebug() << offset << len << length();
        if( len > 0 )
            eraseText( offset, len, m_user );
        else
            kDebug() << "0 legth delete operation. Skipping.";
        checkConsistency();
    }
    else
        kDebug() << "Could not remove text: No local user set.";

}
void PreprocessorCompletionModel::executeCompletionItem2(
    KTextEditor::Document* const doc
  , const KTextEditor::Range& word
  , const QModelIndex& index
  ) const
{
    assert("Invalid index is not expected here!" && index.isValid());
    assert("Parent index is not valid" && index.parent().isValid());
    assert("Parent index must be GROUP" && index.parent().internalId() == Level::GROUP);
    assert("Index points to invalid item" && unsigned(index.row()) < COMPLETIONS.size());

    auto text = COMPLETIONS[index.row()].text;
    const auto column = text.indexOf('|');
    if (column != -1)
        text.remove(column, 1);

    doc->replaceText(word, text);

    // Try to reposition a cursor inside a current view
    if (column != -1)
    {
        auto pos = word.start();
        pos.setColumn(pos.column() + column);
        doc->activeView()->setCursorPosition(pos);
    }
}
Esempio n. 14
0
void SnippetCompletionItem::execute( KTextEditor::View* view, const KTextEditor::Range& word )
{
    QMap< QString, QString > values = QMap<QString, QString>();
    KTextEditor::TemplateInterface2* templateIface2 = qobject_cast<KTextEditor::TemplateInterface2*>(view);
    if (templateIface2)
      templateIface2->insertTemplateText(word.start(), m_snippet, values, m_repo->registeredScript());
}
Esempio n. 15
0
TextRange::TextRange (TextBuffer &buffer, const KTextEditor::Range &range, InsertBehaviors insertBehavior, EmptyBehavior emptyBehavior)
  : m_buffer (buffer)
  , m_start (buffer, this, range.start(), (insertBehavior & ExpandLeft) ? Kate::TextCursor::StayOnInsert : Kate::TextCursor::MoveOnInsert)
  , m_end (buffer, this, range.end(), (insertBehavior & ExpandRight) ? Kate::TextCursor::MoveOnInsert : Kate::TextCursor::StayOnInsert)
  , m_view (0)
  , m_feedback (0)
  , m_zDepth (0.0)
  , m_attributeOnlyForViews (false)
  , m_invalidateIfEmpty (emptyBehavior == InvalidateIfEmpty)
{
  // remember this range in buffer
  m_buffer.m_ranges.insert (this);

  // check if range now invalid, there can happen no feedback, as m_feedback == 0
  checkValidity ();
}
Esempio n. 16
0
void KateViInsertMode::textInserted(KTextEditor::Document* document, KTextEditor::Range range)
{
  if (m_isExecutingCompletion)
  {
    m_textInsertedByCompletion += document->text(range);
    m_textInsertedByCompletionEndPos = range.end();
  }
}
Esempio n. 17
0
void TextRange::setRange (const KTextEditor::Range &range)
{
  // avoid work if nothing changed!
  if (range == toRange())
    return;

  // remember old line range
  int oldStartLine = m_start.line();
  int oldEndLine = m_end.line();

  // change start and end cursor
  m_start.setPosition (range.start ());
  m_end.setPosition (range.end ());

  // check if range now invalid, don't emit feedback here, will be handled below
  // otherwise you can't delete ranges in feedback!
  checkValidity (oldStartLine, oldEndLine, false);

  // no attribute or feedback set, be done
  if (!m_attribute && !m_feedback)
    return;

  // get full range
  int startLineMin = oldStartLine;
  if (oldStartLine == -1 || (m_start.line() != -1 && m_start.line() < oldStartLine))
    startLineMin = m_start.line();

  int endLineMax = oldEndLine;
  if (oldEndLine == -1 || m_end.line() > oldEndLine)
    endLineMax = m_end.line();

  /**
   * notify buffer about attribute change, it will propagate the changes
   * notify right view
   */
  m_buffer.notifyAboutRangeChange (m_view, startLineMin, endLineMax, m_attribute);

  // perhaps need to notify stuff!
  if (m_feedback) {
    // do this last: may delete this range
    if (!toRange().isValid())
      m_feedback->rangeInvalid (this);
    else if (toRange().isEmpty())
      m_feedback->rangeEmpty (this);
  }
}
void PreprocessorCompletionModel::completionInvoked(
    KTextEditor::View* const view
  , const KTextEditor::Range& word
  , InvocationType /*itype*/
  )
{
    // Reuse shouldStartCompletion to disable/enable completion
    m_should_complete = shouldStartCompletion(view, QString{}, false, word.end());
}
    void execute(KTextEditor::View* view, const KTextEditor::Range& word) override
    {
        auto document = view->document();
        auto range = word;
        const int lineNumber = word.end().line();
        const QString line = document->line(lineNumber);
        const auto properties = includePathProperties(line, word.end().column());
        if (!properties.valid) {
            return;
        }

        QString newText = includeItem.isDirectory ? (includeItem.name + QLatin1Char('/')) : includeItem.name;

        if (properties.inputFrom == -1) {
            newText.prepend(QLatin1Char('<'));
        } else {
            range.setStart({lineNumber, properties.inputFrom});
        }
        if (properties.inputTo == -1) {
            // Add suffix
            if (properties.local) {
                newText += QLatin1Char('"');
            } else {
                newText += QLatin1Char('>');
            }

            // replace the whole line
            range.setEnd({lineNumber, line.size()});
        } else {
            range.setEnd({lineNumber, properties.inputTo});
        }

        document->replaceText(range, newText);

        if (includeItem.isDirectory) {
            // ensure we can continue to add files/paths when we just added a directory
            int offset = (properties.inputTo == -1) ? 1 : 0;
            view->setCursorPosition(range.start() + KTextEditor::Cursor(0, newText.length() - offset));
        } else {
            // place cursor at end of line
            view->setCursorPosition({lineNumber, document->lineLength(lineNumber)});
        }
    }
Esempio n. 20
0
QSize GrepOutputDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    const GrepOutputModel *model = dynamic_cast<const GrepOutputModel *>(index.model());
    const GrepOutputItem  *item  = model ? dynamic_cast<const GrepOutputItem *>(model->itemFromIndex(index)) : nullptr;

    QSize ret = QStyledItemDelegate::sizeHint(option, index);

    //take account of additional width required for highlighting (bold text)
    //and line numbers. These are not included in the default Qt size calculation.
    if(item && item->isText())
    {
        QFont font = option.font;
        QFontMetrics metrics(font);
        font.setBold(true);
        QFontMetrics bMetrics(font);

        const KTextEditor::Range rng = item->change()->m_range;

        int width = metrics.width(item->text().left(rng.start().column())) +
                    metrics.width(item->text().right(item->text().length() - rng.end().column())) +
                    bMetrics.width(item->text().mid(rng.start().column(), rng.end().column() - rng.start().column())) +
                    option.fontMetrics.width(i18n("Line %1: ",item->lineNumber())) +
                    std::max(option.decorationSize.width(), 0);
        ret.setWidth(width);
    }else{
        // This is only used for titles, so not very performance critical
        QString text;
        if(item)
            text = item->text();
        else
            text = index.data().toString();
        
        QTextDocument doc;
        doc.setDocumentMargin(0);
        doc.setHtml(text);
        QSize newSize = doc.size().toSize();
        if(newSize.height() > ret.height())
            ret.setHeight(newSize.height());
    }
    return ret;
}
/**
 * We have to stop \c #include completion when current line would parsed well
 * (i.e. contains complete \c #include expression) or have no \c #include at all.
 */
bool IncludeHelperCompletionModel::shouldAbortCompletion(
    KTextEditor::View* view
  , const KTextEditor::Range& range
  , const QString& current_completion
  )
{
    kDebug(DEBUG_AREA) << "range=" << range << ", current_completion=" << current_completion;
    kDebug(DEBUG_AREA) << "m_should_complete=" << m_should_complete << ", closer=" << m_closer;

    // Get current line
    const auto line = view->document()->line(range.end().line());
    // Try to parse it...
    auto r = parseIncludeDirective(line, false);
    // nothing to complete for lines w/o #include
    const auto need_abort = !r.m_range.isValid()
      || range.end().column() < r.m_range.start().column()
      || range.end().column() > (r.m_range.end().column() + 1)
      ;
    kDebug(DEBUG_AREA) << "result=" << need_abort;
    return need_abort;
}
Esempio n. 22
0
bool KateAutoIndent::changeIndent (const KTextEditor::Range &range, int change)
{
  QList<int> skippedLines;

  // loop over all lines given...
  for (int line = range.start().line () < 0 ? 0 : range.start().line ();
       line <= qMin (range.end().line (), doc->lines()-1); ++line)
  {
    // don't indent empty lines
    if (doc->line(line).isEmpty())
    {
      skippedLines.append (line);
      continue;
    }
    // don't indent the last line when the cursor is on the first column
    if (line == range.end().line() && range.end().column() == 0)
    {
      skippedLines.append (line);
      continue;
    }

    doIndentRelative(line, change * indentWidth);
  }

  if (skippedLines.count() > range.numberOfLines())
  {
    // all lines were empty, so indent them nevertheless
    foreach (int line, skippedLines)
      doIndentRelative(line, change * indentWidth);
  }
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);
}
Esempio n. 24
0
void LaTeXCompletionModel::completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range,
                                                                      InvocationType invocationType)
{
	if(!range.isValid()
	|| (invocationType == AutomaticInvocation && !KileConfig::completeAuto())) {
		m_completionList.clear();
		reset();
		return;
	}
	Q_UNUSED(invocationType);
	m_currentView = view;
	KILE_DEBUG() << "building model...";
	buildModel(view, range);
}
Esempio n. 25
0
void TextBuffer::removeText (const KTextEditor::Range &range)
{
  // only allowed if editing transaction running
  Q_ASSERT (m_editingTransactions > 0);

  // only ranges on one line are supported
  Q_ASSERT (range.start().line() == range.end().line());

  // start colum <= end column and >= 0
  Q_ASSERT (range.start().column() <= range.end().column());
  Q_ASSERT (range.start().column() >= 0);

  // skip work, if no text to remove
  if (range.isEmpty())
    return;

  // get block, this will assert on invalid line
  int blockIndex = blockForLine (range.start().line());

  // let the block handle the removeText, retrieve removed text
  QString text;
  m_blocks.at(blockIndex)->removeText (range, text);

  // remember changes
  ++m_revision;

  // update changed line interval
  if (range.start().line() < m_editingMinimalLineChanged || m_editingMinimalLineChanged == -1)
    m_editingMinimalLineChanged = range.start().line();

  if (range.start().line() > m_editingMaximalLineChanged)
    m_editingMaximalLineChanged = range.start().line();

  // emit signal about done change
  emit textRemoved (range, text);
}
Esempio n. 26
0
// Scan throughout the entire document for possible completions,
// ignoring any dublets
const QStringList KateWordCompletionModel::allMatches( KTextEditor::View *view, const KTextEditor::Range &range ) const
{
  QStringList l;

  int i( 0 );
  int pos( 0 );
  KTextEditor::Document *doc = view->document();
  QRegExp re( "\\b(" + doc->text( range ) + "\\w{1,})" );
  QString s, m;
  QSet<QString> seen;

  while( i < doc->lines() )
  {
    s = doc->line( i );
    pos = 0;
    while ( pos >= 0 )
    {
      pos = re.indexIn( s, pos );
      if ( pos >= 0 )
      {
        // typing in the middle of a word
        if ( ! ( i == range.start().line() && pos == range.start().column() ) )
        {
          m = re.cap( 1 );
          if ( ! seen.contains( m ) ) {
            seen.insert( m );
            l << m;
          }
        }
        pos += re.matchedLength();
      }
    }
    i++;
  }
  return l;
}
Esempio n. 27
0
void FunctionDeclarationCompletionItem::executed(KTextEditor::View* view, const KTextEditor::Range& word)
{
    qCDebug(KDEV_PYTHON_CODECOMPLETION) << "FunctionDeclarationCompletionItem executed";
    KTextEditor::Document* document = view->document();
    auto resolvedDecl = Helper::resolveAliasDeclaration(declaration().data());
    DUChainReadLocker lock;
    auto functionDecl = Helper::functionForCalled(resolvedDecl).declaration;
    lock.unlock();
    if ( ! functionDecl && (! resolvedDecl || ! resolvedDecl->abstractType()
                           || resolvedDecl->abstractType()->whichType() != AbstractType::TypeStructure) ) {
        qCritical(KDEV_PYTHON_CODECOMPLETION) << "ERROR: could not get declaration data, not executing completion item!";
        return;
    }
    QString suffix = "()";
    KTextEditor::Range checkPrefix(word.start().line(), 0, word.start().line(), word.start().column());
    KTextEditor::Range checkSuffix(word.end().line(), word.end().column(), word.end().line(), document->lineLength(word.end().line()));
    if ( m_doNotCall || document->text(checkSuffix).trimmed().startsWith('(')
         || document->text(checkPrefix).trimmed().endsWith('@')
         || (functionDecl && Helper::findDecoratorByName(functionDecl, QLatin1String("property"))) )
    {
        // don't insert brackets if they're already there,
        // the item is a decorator, or if it's an import item.
        suffix.clear();
    }
    // place cursor behind bracktes by default
    int skip = 2;
    if ( functionDecl ) {
        bool needsArguments = false;
        int argumentCount = functionDecl->type<FunctionType>()->arguments().length();
        if ( functionDecl->context()->type() == KDevelop::DUContext::Class ) {
            // it's a member function, so it has the implicit self
            // TODO static methods
            needsArguments = argumentCount > 1;
        }
        else {
            // it's a free function
            needsArguments = argumentCount > 0;
        }
        if ( needsArguments ) {
            // place cursor in brackets if there's parameters
            skip = 1;
        }
    }
    document->replaceText(word, declaration()->identifier().toString() + suffix);
    view->setCursorPosition( Cursor(word.end().line(), word.end().column() + skip) );
}
void IncludeHelperCompletionModel::completionInvoked(
    KTextEditor::View* view
  , const KTextEditor::Range& range
  , InvocationType
  )
{
    auto* doc = view->document();
    kDebug(DEBUG_AREA) << range << ", " << doc->text(range);
    const auto& t = doc->line(range.start().line()).left(range.start().column());
    kDebug(DEBUG_AREA) << "text to parse: " << t;
    auto r = parseIncludeDirective(t, false);
    if (r.m_range.isValid())
    {
        m_should_complete = range.start().column() >= r.m_range.start().column()
            && range.start().column() <= r.m_range.end().column();
        if (m_should_complete)
        {
            r.m_range.setBothLines(range.start().line());
            kDebug(DEBUG_AREA) << "parsed range: " << r.m_range;
            m_closer = r.close_char();
            updateCompletionList(doc->text(r.m_range), r.m_type == IncludeStyle::local);
        }
    }
}
void NormalDeclarationCompletionItem::execute(KTextEditor::View* view, const KTextEditor::Range& word) {

    if( m_completionContext && m_completionContext->depth() != 0 )
        return; //Do not replace any text when it is an argument-hint

    KTextEditor::Document* document = view->document();
    QString newText;

    {
        KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock());
        if(m_declaration) {
            newText = declarationName();
        } else {
            qCDebug(LANGUAGE) << "Declaration disappeared";
            return;
        }
    }

    document->replaceText(word, newText);
    KTextEditor::Range newRange = word;
    newRange.setEnd(KTextEditor::Cursor(newRange.end().line(), newRange.start().column() + newText.length()));

    executed(view, newRange);
}
Esempio n. 30
0
void KDocumentTextBuffer::localTextInserted( KTextEditor::Document *document,
    const KTextEditor::Range &range )
{
    if ( m_aboutToClose ) return;

    emit localChangedText(range, user(), false);
    Q_UNUSED(document)

    textOpPerformed();
    if( m_user.isNull() ) {
        kDebug() << "Could not insert text: No local user set.";
        return;
    }
    unsigned int offset = cursorToOffset_kte(range.start());
    kDebug() << "local text inserted" << kDocument() << "( range" << range << ")" << m_user << "offset:" << offset;
    QInfinity::TextChunk chunk(encoding());
    QString text = kDocument()->text(range);
#ifdef ENABLE_TAB_HACK
    if ( text.contains('\t') ) {
        text = text.replace('\t', "    ");
        kDocument()->blockSignals(true);
        kDocument()->replaceText(range, text);
        kDocument()->blockSignals(false);
    }
#endif
    Q_ASSERT(encoder());
    if ( text.isEmpty() ) {
        kDebug() << "Skipping empty insert.";
        return;
    }
    QByteArray encodedText = codec()->fromUnicode( text );
    if ( encodedText.size() == 0 ) {
        kDebug() << "Got empty encoded text from non empty string "
                    "Skipping insertion";
    }
    else {
        chunk.insertText( 0, encodedText, countUnicodeCharacters(text), m_user->id() );
        blockRemoteInsert = true;
        kDebug() << "inserting chunk of size" << chunk.length() << "into local buffer" << kDocument()->url();
        insertChunk( offset, chunk, m_user );
        kDebug() << "done inserting chunk";
        checkConsistency();
    }
}