IAssistProposal *ProFileCompletionAssistProcessor::perform(const IAssistInterface *interface)
{
    m_interface.reset(interface);

    if (isInComment())
        return 0;

    if (interface->reason() == IdleEditor && !acceptsIdleEditor())
        return 0;

    if (m_startPosition == -1)
        m_startPosition = findStartOfName();

    QList<TextEditor::BasicProposalItem *> items;
    QStringList keywords = ProFileKeywords::variables() + ProFileKeywords::functions();
    for (int i = 0; i < keywords.count(); i++) {
        BasicProposalItem *item = new ProFileAssistProposalItem;
        item->setText(keywords[i]);
        item->setIcon(ProFileKeywords::isFunction(item->text()) ? m_functionIcon : m_variableIcon);
        items.append(item);
    }

    return new GenericProposal(m_startPosition, new ProFileAssistProposalModel(items));
}
uint qHash(const BasicProposalItem &item)
{
    return qHash(item.text());
}
void BasicProposalItemListModel::filter(const QString &prefix)
{
    if (prefix.isEmpty())
        return;

    /*
     * This code builds a regular expression in order to more intelligently match
     * camel-case and underscore names.
     *
     * For any but the first letter, the following replacements are made:
     *   A => [a-z0-9_]*A
     *   a => (?:[a-zA-Z0-9]*_)?a
     *
     * That means any sequence of lower-case or underscore characters can preceed an
     * upper-case character. And any sequence of lower-case or upper case characters -
     * followed by an underscore can preceed a lower-case character.
     *
     * Examples: (case sensitive mode)
     *   gAC matches getActionController
     *   gac matches get_action_controller
     *
     * It also implements the fully and first-letter-only case sensitivity.
     */
    const TextEditor::CaseSensitivity caseSensitivity =
        TextEditorSettings::instance()->completionSettings().m_caseSensitivity;

    QString keyRegExp;
    keyRegExp += QLatin1Char('^');
    bool first = true;
    const QLatin1String uppercaseWordContinuation("[a-z0-9_]*");
    const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?");
    foreach (const QChar &c, prefix) {
        if (caseSensitivity == TextEditor::CaseInsensitive ||
            (caseSensitivity == TextEditor::FirstLetterCaseSensitive && !first)) {

            keyRegExp += QLatin1String("(?:");
            if (!first)
                keyRegExp += uppercaseWordContinuation;
            keyRegExp += QRegExp::escape(c.toUpper());
            keyRegExp += QLatin1Char('|');
            if (!first)
                keyRegExp += lowercaseWordContinuation;
            keyRegExp += QRegExp::escape(c.toLower());
            keyRegExp += QLatin1Char(')');
        } else {
            if (!first) {
                if (c.isUpper())
                    keyRegExp += uppercaseWordContinuation;
                else
                    keyRegExp += lowercaseWordContinuation;
            }
            keyRegExp += QRegExp::escape(c);
        }

        first = false;
    }
    QRegExp regExp(keyRegExp);

    m_currentItems.clear();
    for (QList<BasicProposalItem *>::const_iterator it = m_originalItems.begin();
         it != m_originalItems.end();
         ++it) {
        BasicProposalItem *item = *it;
        if (regExp.indexIn(item->text()) == 0)
            m_currentItems.append(item);
    }
}