Example #1
0
//Returns only the name, no template-parameters or scope
QString cursorItemText() {
  KDevelop::DUChainReadLocker lock( DUChain::lock() );

  Declaration* decl = cursorDeclaration();
  if(!decl)
    return QString();

  IDocument* doc = ICore::self()->documentController()->activeDocument();
  if(!doc)
    return QString();

  TopDUContext* context = DUChainUtils::standardContextForUrl( doc->url() );

  if( !context ) {
    qCDebug(PLUGIN_QUICKOPEN) << "Got no standard context";
    return QString();
  }

  AbstractType::Ptr t = decl->abstractType();
  IdentifiedType* idType = dynamic_cast<IdentifiedType*>(t.data());
  if( idType && idType->declaration(context) )
    decl = idType->declaration(context);

  if(!decl->qualifiedIdentifier().isEmpty())
    return decl->qualifiedIdentifier().last().identifier().str();

  return QString();
}
void ContextBuilder::addBaseType( KDevelop::BaseClassInstance base, BaseSpecifierAST *node ) {
  DUChainWriteLocker lock(DUChain::lock());

  addImportedContexts(); //Make sure the template-contexts are imported first, before any parent-class contexts.

  Q_ASSERT(currentContext()->type() == DUContext::Class);
  AbstractType::Ptr baseClass = base.baseClass.abstractType();
  IdentifiedType* idType = dynamic_cast<IdentifiedType*>(baseClass.unsafeData());
  Declaration* idDecl = 0;
  if( idType && (idDecl = idType->declaration(currentContext()->topContext())) ) {
    DUContext* ctx = idDecl->logicalInternalContext(currentContext()->topContext());
    if(ctx) {
      currentContext()->addImportedParentContext( ctx );
    }else{
      currentContext()->addIndirectImport( DUContext::Import(idType->declarationId()) );
      QString text = i18n("Could not resolve base class, adding it indirectly: %1", (base.baseClass ? base.baseClass.abstractType()->toString() : QString()));
      lock.unlock();
      createUserProblem(node, text);
    }
  } else if( !baseClass.cast<DelayedType>() ) {
    QString text = i18n("Invalid base class: %1", (base.baseClass ? base.baseClass.abstractType()->toString() : QString()));
    lock.unlock();
    createUserProblem(node, text);
  }
}
Example #3
0
AbstractType::Ptr TypeRepository::registerType(AbstractType::Ptr input)
{
  if (!input) {
    kWarning(9007) << "Asked to register a null type." ;
    return input;
  }

  switch (input->whichType()) {
    case AbstractType::TypeAbstract:
      return input;

    case AbstractType::TypeIntegral:
      return input;

    case AbstractType::TypePointer:
      return registerPointer(CppPointerType::Ptr::dynamicCast(input));

    case AbstractType::TypeReference:
      return registerReference(CppReferenceType::Ptr::dynamicCast(input));

    case AbstractType::TypeFunction:
      return registerFunction(CppFunctionType::Ptr::dynamicCast(input));

    case AbstractType::TypeStructure:
      return input;

    case AbstractType::TypeArray:
      return registerArray(ArrayType::Ptr::dynamicCast(input));

    case AbstractType::TypeDelayed:
      return registerDelayedType(DelayedType::Ptr::dynamicCast(input));
    default:
      return input;
  }
}
QList< TypePtr< StructureType > > ExpressionVisitor::possibleStructureTypes(AbstractType::Ptr type)
{
    QList< TypePtr< StructureType > > result;
    type = Helper::resolveType(type);
    if ( ! type ) {
        return result;
    }
    if ( type->whichType() == KDevelop::AbstractType::TypeUnsure ) {
        AbstractType::Ptr current;
        UnsureType::Ptr possible = type.cast<UnsureType>();
        int amount = possible->typesSize();
        for ( int i = 0; i < amount; i++ ) {
            StructureType::Ptr current = Helper::resolveType(possible->types()[i].abstractType()).cast<StructureType>();
            if ( current ) {
                result << current;
            }
        }
    }
    else {
        StructureType::Ptr c = type.cast<StructureType>();
        if ( c ) {
            result << c;
        }
    }
    return result;
}
Example #5
0
AbstractType::Ptr mergeTypes(AbstractType::Ptr type, const AbstractType::Ptr newType)
{
    if (newType && newType->whichType() == AbstractType::TypeFunction) {
        return newType;
    } else {
        return TypeUtils::mergeTypes(type, newType);
    }
}
AbstractType::Ptr binaryOperatorReturnType(AbstractType::Ptr left, AbstractType::Ptr right, int tokenKind) {

  if(!left || !right)
    return AbstractType::Ptr();

  IntegralType* leftIntegral = dynamic_cast<IntegralType*>(left.unsafeData());
  IntegralType* rightIntegral = dynamic_cast<IntegralType*>(right.unsafeData());
  PointerType* leftPointer = dynamic_cast<PointerType*>(right.unsafeData());

  AbstractType::Ptr ret;

  //Constantly evaluate integral expressions
  ConstantIntegralType* leftConstantIntegral = dynamic_cast<ConstantIntegralType*>(left.unsafeData());
  ConstantIntegralType* rightConstantIntegral = dynamic_cast<ConstantIntegralType*>(right.unsafeData());

  if(leftIntegral && rightIntegral) {
    if(tokenKind == '+' || tokenKind == '-' || tokenKind == '*' || tokenKind == '/' || tokenKind == '%' || tokenKind == '^' || tokenKind == '&' || tokenKind == '|' || tokenKind == '~' || tokenKind == Token_shift) {
      if(moreExpressiveThan(leftIntegral, rightIntegral))
        ret = left;
      else
        ret = right;
    }

    if(tokenKind == '<' || tokenKind == '>' || tokenKind == Token_eq || tokenKind == Token_not_eq || tokenKind == Token_leq || tokenKind == Token_geq || tokenKind == Token_not_eq || tokenKind == Token_and || tokenKind == Token_or)
      ret = AbstractType::Ptr(new IntegralType(IntegralType::TypeBoolean));
  }

  if(leftPointer && rightIntegral && (tokenKind == '+' || tokenKind == '-'))
    ret = left;

  IntegralType* retIntegral = dynamic_cast<IntegralType*>(ret.unsafeData());

  ///We have determined the resulting type now. If both sides are constant, also evaluate the resulting value.
  if(ret && retIntegral && leftConstantIntegral && rightConstantIntegral) {
    switch( retIntegral->dataType() ) {
      case IntegralType::TypeFloat:
      {
        ConstantBinaryExpressionEvaluator<float> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral );
        return evaluator.createType();
      }
      case IntegralType::TypeDouble:
      {
        ConstantBinaryExpressionEvaluator<double> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral );
        return evaluator.createType();
      }
      default:
        if( leftConstantIntegral->modifiers() & AbstractType::UnsignedModifier ) {
          ConstantBinaryExpressionEvaluator<quint64> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral);
          return evaluator.createType();
        } else {
          ConstantBinaryExpressionEvaluator<qint64> evaluator( retIntegral->dataType(), retIntegral->modifiers(), tokenKind, leftConstantIntegral, rightConstantIntegral);
          return evaluator.createType();
        }
        break;
    }
  }
  return ret;
}
Example #7
0
uint TypeRepository::indexForType(const AbstractType::Ptr input) {
  if(!input)
    return 0;

  uint i = typeRepository()->index(AbstractTypeDataRequest(*input));
#ifdef DEBUG_TYPE_REPOSITORY
  AbstractType::Ptr t = typeForIndex(i);
  if(!t->equals(input.data())) {
      qCWarning(LANGUAGE) << "found type in repository does not equal source type:" << input->toString() << t->toString();
      t->equals(input.data());
  }
#ifdef ASSERT_ON_PROBLEM
  Q_ASSERT(t->equals(input.data()));
  Q_ASSERT(input->equals(t.data()));
#endif
#endif
  return i;
}
Example #8
0
QList<CompletionTreeItemPointer> CodeCompletionContext::getCompletionItemsFromType(AbstractType::Ptr type, bool scoped)
{
    QList<CompletionTreeItemPointer> res;
    if (type->whichType() == AbstractType::TypeUnsure) {
        UnsureType::Ptr unsure = type.cast<UnsureType>();
        int count = unsure->typesSize();
        for (int i = 0; i < count; i++) {
            res.append(getCompletionItemsForOneType(unsure->types()[i].abstractType(), scoped));
        }
    } else {
        res = getCompletionItemsForOneType(type, scoped);
    }
    return res;
}
Example #9
0
void ADLHelper::addArgumentType(const AbstractType::Ptr typePtr)
{
    if(m_alreadyProcessed.contains(typePtr.data()))
      return;

    if (typePtr)
    {
#ifdef DEBUG_ADL
        qCDebug(CPPDUCHAIN) << "    added argument type " << typePtr->toString() << " to ADL lookup";
#endif
        // the enumeration and enumerator types are not part of the TypeVisitor interface
        switch (typePtr->whichType())
        {
        case AbstractType::TypeEnumeration:
        {
            EnumerationType* specificType = fastCast<EnumerationType*>(typePtr.data());
            if (specificType)
            {
                Declaration * enumDecl = specificType->declaration(m_topContext.data());
                addDeclarationScopeIdentifier(enumDecl);
            }
            break;
        }
        case AbstractType::TypeEnumerator:
        {
            if (m_templateArgsDepth == 0)
            {
                EnumeratorType* specificType = fastCast<EnumeratorType*>(typePtr.data());
                if (specificType)
                {
                    // use the enumeration context for the enumerator value declaration to find out the namespace
                    Declaration * enumeratorDecl = specificType->declaration(m_topContext.data());
                    if (enumeratorDecl) {
                        DUContext * enumContext = enumeratorDecl->context();
                        if (enumContext) {
                            addAssociatedNamespace(enumContext->scopeIdentifier(false));
                        }
                    }
                }
            }
            break;
        }
        default:
            typePtr->accept(&m_typeVisitor);
        }
    }

    m_alreadyProcessed.insert(typePtr.data());
}
void ExpressionVisitor::encounter(AbstractType::Ptr type, EncounterFlags flags)
{
    if ( type )
        kDebug() << "type encountered: " << type->toString();
    else
        kDebug() << "unknown type encountered";
    if ( flags & AutomaticallyDetermineDeclaration ) {
        StructureType::Ptr t = type.cast<StructureType>();
        if ( t ) {
            encounterDeclaration(t->declaration(m_ctx->topContext()));
        }
        else {
            encounterDeclaration(0);
        }
    }
    m_lastType.push(encounterPreprocess(type, flags & MergeTypes));
}
Example #11
0
void ImplementationItem::execute(KTextEditor::View* view, const KTextEditor::Range& word)
{
    DUChainReadLocker lock(DUChain::lock());
    KTextEditor::Document *document = view->document();

    QString replText;

    if (m_declaration) {
        //TODO:respect custom code styles

        // get existing modifiers so we can respect the user's choice of public/protected and final
        QStringList modifiers = getMethodTokens(document->text(KTextEditor::Range(KTextEditor::Cursor::start(), word.start())));
        // get range to replace
        KTextEditor::Range replaceRange(word);
        if (!modifiers.isEmpty()) {
            // TODO: is there no easy API to map QString Index to a KTextEditor::Cursor ?!
            QString methodText = document->text(KTextEditor::Range(KTextEditor::Cursor::start(), word.start()));
            methodText = methodText.left(methodText.lastIndexOf(modifiers.last(), -1, Qt::CaseInsensitive));
            replaceRange.start() = KTextEditor::Cursor(methodText.count('\n'), methodText.length() - methodText.lastIndexOf('\n') - 1);
        }

        // get indendation
        QString indendation;
        {
            QString currentLine = document->line(replaceRange.start().line());
            indendation = getIndendation(currentLine);

            if ( !currentLine.isEmpty() && currentLine != indendation ) {
                // since theres some non-whitespace in this line, skip to the enxt one
                replText += '\n' + indendation;
            }

            if (indendation.isEmpty()) {
                // use a minimal indendation
                // TODO: respect code style
                indendation = QStringLiteral("  ");
                replText += indendation;
            }
        }

        #if 0
        //Disabled, because not everyone writes phpdoc for every function
        //TODO: move to a phpdoc helper
        // build phpdoc comment
        {
            QualifiedIdentifier parentClassIdentifier;
            if (DUContext* pctx = m_declaration->context()) {
                parentClassIdentifier = pctx->localScopeIdentifier();
            } else {
                qCDebug(COMPLETION) << "completion item for implementation has no parent context!";
            }

            replText += "/**\n" + indendation + " * ";
            // insert old comment:
            const QString indentationWithExtra = "\n" + indendation + " *";
            replText += m_declaration->comment().replace('\n', indentationWithExtra.toAscii().constData());
            replText += "\n" + indendation + " * @overload " + m_declaration->internalContext()->scopeIdentifier(true).toString();
            replText += "\n" + indendation + " **/\n" + indendation;
        }
        #endif

        // write function signature

        // copy existing modifiers
        if (!modifiers.isEmpty()) {
            // the tokens are in a bad order and there's no reverse method or similar, so we can't simply join the tokens
            QStringList::const_iterator i = modifiers.constEnd() - 1;
            while (true) {
                replText += (*i) + ' ';
                if (i == modifiers.constBegin()) {
                    break;
                } else {
                    --i;
                }
            }
        }

        QString functionName;
        bool isConstructorOrDestructor = false;
        bool isInterface = false;

        if (ClassMemberDeclaration* member = dynamic_cast<ClassMemberDeclaration*>(m_declaration.data())) {
            // NOTE: it should _never_ be private - but that's the completionmodel / context / worker's job
            if (!modifiers.contains(QStringLiteral("public")) && !modifiers.contains(QStringLiteral("protected"))) {
                if (member->accessPolicy() == Declaration::Protected) {
                    replText += QLatin1String("protected ");
                } else {
                    replText += QLatin1String("public ");
                }
            }
            if (!modifiers.contains(QStringLiteral("static")) && member->isStatic()) {
                replText += QLatin1String("static ");
            }
            functionName = member->identifier().toString();

            ClassMethodDeclaration* method = dynamic_cast<ClassMethodDeclaration*>(m_declaration.data());
            if (method) {
                functionName = method->prettyName().str();
                isConstructorOrDestructor = method->isConstructor() || method->isDestructor();
            }

            if (member->context() && member->context()->owner()) {
                ClassDeclaration* classDec = dynamic_cast<ClassDeclaration*>(member->context()->owner());
                if (classDec) {
                    isInterface = (classDec->classType() == ClassDeclarationData::Interface);
                }
            }
        } else {
            qCDebug(COMPLETION) << "completion item for implementation was not a classfunction declaration!";
            functionName = m_declaration->identifier().toString();
        }

        if (m_type == ImplementationItem::OverrideVar) {
            replText += "$" + functionName + " = ";
        } else {
            if (!modifiers.contains(QStringLiteral("function"))) {
                replText += QLatin1String("function ");
            }

            replText += functionName;

            {
                // get argument list
                QString arguments;
                createArgumentList(*this, arguments, 0, true);
                replText += arguments;
            }

            QString arguments;
            QVector<Declaration*> parameters;
            if (DUChainUtils::getArgumentContext(m_declaration.data()))
                parameters = DUChainUtils::getArgumentContext(m_declaration.data())->localDeclarations();
            arguments = '(';
            bool first = true;
            foreach(Declaration* dec, parameters) {
                if (first)
                    first = false;
                else
                    arguments += QLatin1String(", ");

                arguments += '$' + dec->identifier().toString();
            }
            arguments += ')';

            bool voidReturnType = false;
            if (FunctionType::Ptr::dynamicCast(m_declaration->abstractType())) {
                AbstractType::Ptr retType = FunctionType::Ptr::staticCast(m_declaration->abstractType())->returnType();
                if (retType->equals(new IntegralType(IntegralType::TypeVoid))) {
                    voidReturnType = true;
                }
            }

            replText += QStringLiteral("\n%1{\n%1    ").arg(indendation);
            if (isInterface || m_type == ImplementationItem::Implement) {
            } else if (!isConstructorOrDestructor && !voidReturnType) {
                replText += QStringLiteral("$ret = parent::%2%3;\n%1    return $ret;").arg(indendation, functionName, arguments);
            } else {
                replText += QStringLiteral("parent::%1%2;").arg(functionName, arguments);
            }
            replText += QStringLiteral("\n%1}\n%1")
                    .arg(indendation);

        }


        //TODO: properly place the cursor inside the {} part
        document->replaceText(replaceRange, replText);

    } else {
Example #12
0
void FunctionType::setReturnType(AbstractType::Ptr returnType)
{
  d_func_dynamic()->m_returnType = returnType->indexed();
}
Example #13
0
QVariant CompletionItem::data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const
{
    switch(role)
    {
        case Qt::DisplayRole:
        {
            if (index.column() == CodeCompletionModel::Prefix && m_prefix != "") {
                return m_prefix;
            }
            break;
        }
        case CodeCompletionModel::BestMatchesCount:
            return 5;
        case CodeCompletionModel::MatchQuality:
        {
            if(!declaration())
                return QVariant();
            //type aliases are actually different types
            if(declaration()->isTypeAlias())
                return QVariant();
            AbstractType::Ptr typeToMatch = static_cast<go::CodeCompletionContext*>(model->completionContext().data())->typeToMatch();
            if(!typeToMatch)
                return QVariant();
            AbstractType::Ptr declType = declaration()->abstractType();
            if (!declType)
                return QVariant();
            //ignore constants
            typeToMatch->setModifiers(AbstractType::NoModifiers);
            declType->setModifiers(AbstractType::NoModifiers);
            if(declType->equals(typeToMatch.constData()))
            {
                return QVariant(10);
            }
            else if(declType->whichType() == AbstractType::TypeFunction)
            {
                GoFunctionType* function = fastCast<GoFunctionType*>(declType.constData());
                auto args = function->returnArguments();
                if(args.size() != 0)
                {
                    AbstractType::Ptr first = args.first();
                    first->setModifiers(AbstractType::NoModifiers);
                    if(first->equals(typeToMatch.constData()))
                        return QVariant(10);
                }
            }else
            {
                return QVariant();
            }
        }
    }
    return NormalDeclarationCompletionItem::data(index, role, model);
}
Example #14
0
void PointerType::setBaseType(AbstractType::Ptr type)
{
  d_func_dynamic()->m_baseType = type->indexed();
}
Example #15
0
void GoChanType::setValueType(AbstractType::Ptr type)
{
    d_func_dynamic()->valueType = type->indexed();
}