Beispiel #1
0
void DeclarationBuilder::visitAliasStatement(Ast *node)
{
    Ast *right = new Ast(node->tree->r, node->context);
    QualifiedIdentifier id = QualifiedIdentifier(QString(right->tree->name));
    const RangeInRevision &range = editorFindRange(right, right);
    DeclarationPointer decl = getDeclaration(id, range, DUContextPointer(currentContext()));

    if (is_global_var(node->tree->l) && is_global_var(right->tree)) {
        DUChainWriteLocker wlock;
        // If the global variable on the right is not declared, declare it as nil
        if (!decl) {
            AbstractType::Ptr type = topContext()->findDeclarations(QualifiedIdentifier("NilClass")).first()->abstractType();
            VariableDeclaration *vDecl = openDefinition<VariableDeclaration>(id, range);
            vDecl->setVariableKind(right->tree);
            vDecl->setKind(Declaration::Instance);
            vDecl->setType(type);
            eventuallyAssignInternalContext();
            DeclarationBuilderBase::closeDeclaration();
            decl = vDecl;
        }
        node->tree = node->tree->l;
        QualifiedIdentifier aid = getIdentifier(node);
        AbstractType::Ptr type = decl->abstractType();
        declareVariable(aid, type, node);
    } else if (decl && decl->isFunctionDeclaration()) {
        DUChainWriteLocker wlock;
        MethodDeclaration *md = dynamic_cast<MethodDeclaration *>(decl.data());
        node->tree = node->tree->l;
        const RangeInRevision & arange = editorFindRange(node, node);
        QualifiedIdentifier aid = getIdentifier(node);
        aliasMethodDeclaration(aid, arange, md);
    } else
        appendProblem(node->tree, i18n("undefined method `%1'", id.toString()));
}
Beispiel #2
0
IndexedTypeIdentifier typeIdentifierFromTemplateArgument(ParseSession* session, TemplateArgumentAST *node)
{
  IndexedTypeIdentifier id;
  if(node->expression) {
    id = IndexedTypeIdentifier(session->stringForNode(node), true);
  }else if(node->type_id) {
    //Parse the pointer operators
    TypeCompiler tc(session);
    tc.run(node->type_id->type_specifier);
    id = IndexedTypeIdentifier(tc.identifier());
    //node->type_id->type_specifier->cv
    
    if(node->type_id->type_specifier)
      id.setIsConstant(parseConstVolatile(session, node->type_id->type_specifier->cv) & AbstractType::ConstModifier);
    
    if(node->type_id->declarator && node->type_id->declarator->ptr_ops)
    {
      const ListNode<PtrOperatorAST*> *it = node->type_id->declarator->ptr_ops->toFront();
      const ListNode<PtrOperatorAST*> *end = it; ///@todo check ordering, eventually walk the list in reversed order
      do
        {
          if(it->element && it->element->op) { ///@todo What about ptr-to-member?
            int kind = session->token_stream->kind(it->element->op);
            if(kind == '&') {
              //We're handling a 'reference'
              id.setIsReference(true);
            } else if(kind == Token_and) {
              //We're handling an rvalue-reference
              id.setIsReference(true);
              id.setIsRValue(true);
            } else {
              //We're handling a real pointer
              id.setPointerDepth(id.pointerDepth()+1);

              if(it->element->cv) {
                id.setIsConstPointer(id.pointerDepth()-1, parseConstVolatile(session, it->element->cv) & AbstractType::ConstModifier);
              }
            }
          }
          it = it->next;
        }
      while (it != end);
    } else if (node->type_id->declarator && node->type_id->declarator->array_dimensions) {
      ///FIXME: find a way to put this information into the identifier
      ///       e.g.: id.setArrayDepth(id.arrayDepth() + 1) ?
      const ListNode< ExpressionAST* >* it = node->type_id->declarator->array_dimensions->toFront();
      const ListNode< ExpressionAST* >* end = node->type_id->declarator->array_dimensions-> toBack();
      do {
        QualifiedIdentifier qid = id.identifier();
        Identifier last = qid.last();
        qid.pop();
        last.setIdentifier(last.toString() + "[]");
        qid.push(last);
        id.setIdentifier(IndexedQualifiedIdentifier( qid ));
        it = it->next;
      } while (it != end);
    }
  }
  return id;
}
QualifiedIdentifier InstantiationInformation::applyToIdentifier(const QualifiedIdentifier& id) const {
  QualifiedIdentifier ret;
  if(id.count() > 1) {
    ret = id;
    ret.pop();
    if(previousInstantiationInformation.index())
      ret = previousInstantiationInformation.information().applyToIdentifier(ret);
  }

  Identifier lastId(id.last());

  KDevVarLengthArray<IndexedTypeIdentifier> oldTemplateIdentifiers;
  for(uint a = 0; a < lastId.templateIdentifiersCount(); ++a)
    oldTemplateIdentifiers.append(lastId.templateIdentifier(a)); 
  lastId.clearTemplateIdentifiers();

  for(uint a = 0; a < templateParametersSize(); ++a) {
    if(templateParameters()[a].abstractType()) {
      lastId.appendTemplateIdentifier(IndexedTypeIdentifier(templateParameters()[a].abstractType()->toString(), true));
    }else{
      lastId.appendTemplateIdentifier((uint) oldTemplateIdentifiers.size() > a ? oldTemplateIdentifiers[a] : IndexedTypeIdentifier());
    }
  }

  for(int a = templateParametersSize(); a < oldTemplateIdentifiers.size(); ++a)
    lastId.appendTemplateIdentifier(oldTemplateIdentifiers[a]);

  ret.push(lastId);
  return ret;
}
void NamespaceAliasDeclaration::registerAliasIdentifier()
{
  if(indexedIdentifier() != globalImportIdentifier())
  {
    QualifiedIdentifier aliasId = qualifiedIdentifier();
    aliasId.push(globalAliasIdentifier());
    KDevelop::PersistentSymbolTable::self().addDeclaration(aliasId, this);
  }
}
QList<QVariant> DUChainItemData::highlighting() const
{
  DUChainReadLocker lock;;

  Declaration* decl = m_item.m_item.data();
  if(!decl) {
    return QList<QVariant>();
  }

  if(FunctionDefinition* def = dynamic_cast<FunctionDefinition*>(decl)) {
    if(def->declaration()) {
      decl = def->declaration();
    }
  }

  QTextCharFormat boldFormat;
  boldFormat.setFontWeight(QFont::Bold);
  QTextCharFormat normalFormat;

  int prefixLength = 0;

  QString signature;
  TypePtr<FunctionType> function = decl->type<FunctionType>();
  if(function) {
    signature = function->partToString( FunctionType::SignatureArguments );
  }

  //Only highlight the last part of the qualified identifier, so the scope doesn't distract too much
  QualifiedIdentifier id = decl->qualifiedIdentifier();
  QString fullId = id.toString();
  QString lastId;
  if(!id.isEmpty()) {
    lastId = id.last().toString();
  }

  prefixLength += fullId.length() - lastId.length();

  QList<QVariant> ret;
  ret << 0;
  ret << prefixLength;
  ret << QVariant(normalFormat);
  ret << prefixLength;
  ret << lastId.length();
  ret << QVariant(boldFormat);
  if(!signature.isEmpty()) {
    ret << prefixLength + lastId.length();
    ret << signature.length();
    ret << QVariant(normalFormat);
  }

  return ret;

}
Beispiel #6
0
QString CppClassType::toString() const
{
  QualifiedIdentifier id = qualifiedIdentifier();
  if (!id.isEmpty()) {
    if(declarationId().specialization().index())
      return AbstractType::toString() + Cpp::IndexedInstantiationInformation(declarationId().specialization()).information().applyToIdentifier(id).toString();
    else
    return AbstractType::toString() + id.toString();
  }

  //This path usually is not taken
  QString type = "class";

  return QString("<%1>%2").arg(type).arg(AbstractType::toString(true));
}
Beispiel #7
0
void UseBuilder::visitTraitAliasStatement(TraitAliasStatementAst *node)
{
    if (node->conflictIdentifierSequence) {
        const KDevPG::ListNode< NamespacedIdentifierAst* >* it = node->conflictIdentifierSequence->front();
        forever {
            buildNamespaceUses(it->element, ClassDeclarationType);

            if ( it->hasNext() ) {
                it = it->next;
            } else {
                break;
            }
        }
    }

    DUChainWriteLocker lock;
    DeclarationPointer dec = findDeclarationImport(ClassDeclarationType, identifierForNamespace(node->importIdentifier->identifier, m_editor));

    if (dec) {
        QualifiedIdentifier original = identifierPairForNode(node->importIdentifier->methodIdentifier).second;
        QList <Declaration*> list = dec.data()->internalContext()->findLocalDeclarations(original.last(), dec.data()->internalContext()->range().start);

        if (!list.isEmpty()) {
            UseBuilderBase::newUse(node->importIdentifier->methodIdentifier, DeclarationPointer(list.first()));
        }
    }

    lock.unlock();

    visitTraitAliasIdentifier(node->importIdentifier);
}
QString ClassSpecializationType::toString() const
{
    QualifiedIdentifier id = qualifiedIdentifier();
    if (!id.isEmpty()) {
        QString result = AbstractType::toString() + strippedQid(id) + QLatin1String("< ");
        bool first = true;
        for (const auto& param : templateParameters()) {
            if (first) {
                first = false;
            } else {
                result += QLatin1String(", ");
            }
            result += param.abstractType()->toString();
        }
        result += QLatin1String(" >");
        return result;
    }

    return StructureType::toString();
}
QPair<DUContext*, QualifiedIdentifier> ContextBuilder::findPrefixContext(const QualifiedIdentifier& id, KDevelop::SimpleCursor pos) {
  if(id.count() < 2)
    return qMakePair((DUContext*)0, QualifiedIdentifier());
  
  QualifiedIdentifier prefixId(id);
  prefixId.pop();

  DUContext* import = 0;

  {
    DUChainReadLocker lock(DUChain::lock());

    QualifiedIdentifier currentScopeId = currentContext()->scopeIdentifier(true);

    QList<Declaration*> decls = currentContext()->findDeclarations(prefixId, pos);

    if(!decls.isEmpty()) {
      DUContext* classContext = decls.first()->logicalInternalContext(0);
      if(classContext && classContext->type() == DUContext::Class) {
        import = classContext;
        //Change the prefix-id so it respects namespace-imports
        
        prefixId = classContext->scopeIdentifier(true);
        if(prefixId.count() >= currentScopeId.count() && prefixId.left(currentScopeId.count()) == currentScopeId)
          prefixId = prefixId.mid(currentScopeId.count());
        else
          kDebug() << "resolved bad prefix context. Should start with" << currentScopeId.toString() << "but is" << prefixId.toString();
      }
    }
  }
  
  return qMakePair(import, prefixId);
}
Beispiel #10
0
DeclarationPointer getDeclaration(const QualifiedIdentifier& id, const DUContext* context, bool searchInParent)
{
    DUChainReadLocker lock;
    if (context) {
        auto declarations = context->findDeclarations(
            id.indexedLast(),
            CursorInRevision(INT_MAX, INT_MAX),
            nullptr,
            searchInParent ? DUContext::NoSearchFlags : DUContext::DontSearchInParent
        );

        if (declarations.count() > 0) {
            return DeclarationPointer(declarations.last());
        }
    }
    return DeclarationPointer();
}
void ContextBuilder::openPrefixContext(AST* ast, const QualifiedIdentifier& id, const SimpleCursor& pos) {
  if(id.count() < 2)
    return;

  //When creating a prefix-context that is there to embed a class within another class, import the enclosing class into that context.
  //That way items from the base class can be found.

  QPair<DUContext*, QualifiedIdentifier> prefix = findPrefixContext(id, pos);

  openContext(ast, DUContext::Helper, prefix.second);

  DUContext* import = prefix.first;
  
  if(import) {
    DUChainWriteLocker lock(DUChain::lock());
    addImportedParentContextSafely(currentContext(), import);
  }
}
Beispiel #12
0
DeclarationPointer getDeclarationOrSignal(const QualifiedIdentifier& id, const DUContext* context, bool searchInParent)
{
    QString identifier = id.last().toString();

    if (identifier.startsWith(QLatin1String("on")) && identifier.size() > 2) {
        // The use may have typed the name of a QML slot (onFoo), try to get
        // the declaration of its corresponding signal (foo)
        identifier = identifier.at(2).toLower() + identifier.mid(3);
        DeclarationPointer decl = getDeclaration(QualifiedIdentifier(identifier), context, searchInParent);

        if (decl) {
            ClassFunctionDeclaration* classFuncDecl = dynamic_cast<ClassFunctionDeclaration *>(decl.data());

            if (classFuncDecl && classFuncDecl->isSignal()) {
                // Removing "on" has given the identifier of a QML signal, return
                // it instead of the name of its slot
                return decl;
            }
        }
    }

    // No signal found, fall back to normal behavior
    return getDeclaration(id, context, searchInParent);
}
QString DeclarationNavigationContext::html(bool shorten)
{
  clear();
  m_shorten = shorten;
  modifyHtml()  += "<html><body><p>" + fontSizePrefix(shorten);

  addExternalHtml(m_prefix);

  if(!m_declaration.data()) {
    modifyHtml() += i18n("<br /> lost declaration <br />");
    return currentHtml();
  }
  
  if( m_previousContext ) {
    QString link = createLink( m_previousContext->name(), m_previousContext->name(), NavigationAction(m_previousContext) );
    modifyHtml() += navigationHighlight(i18n("Back to %1<br />", link));
  }
  
  QExplicitlySharedDataPointer<IDocumentation> doc;
  
  if( !shorten ) {
    doc = ICore::self()->documentationController()->documentationForDeclaration(m_declaration.data());

    const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(m_declaration.data());
    if( function ) {
      htmlFunction();
    } else if( m_declaration->isTypeAlias() || m_declaration->kind() == Declaration::Instance ) {
	
	
      if( m_declaration->isTypeAlias() )
        modifyHtml() += importantHighlight("type ");

      if(m_declaration->type<EnumeratorType>())
        modifyHtml() += i18n("enumerator ");
      
      if( !m_declaration->isTypeAlias()) 
          modifyHtml() += ' ' + identifierHighlight(declarationName(m_declaration).toHtmlEscaped(), m_declaration) + " ";

      AbstractType::Ptr useType = m_declaration->abstractType();
      if(m_declaration->isTypeAlias()) {
        //Do not show the own name as type of typedefs
        if(useType.cast<TypeAliasType>())
          useType = useType.cast<TypeAliasType>()->type();
      } 
      
      eventuallyMakeTypeLinks( useType );
      
      modifyHtml() += "<br>";

    }else{
      if( m_declaration->kind() == Declaration::Type && m_declaration->abstractType().cast<StructureType>()) {
        htmlClass();
      }
      if ( m_declaration->kind() == Declaration::Namespace ) {
        modifyHtml() += i18n("namespace %1 ", identifierHighlight(m_declaration->qualifiedIdentifier().toString().toHtmlEscaped(), m_declaration));
      }

      if(m_declaration->type<EnumerationType>()) {
        EnumerationType::Ptr enumeration = m_declaration->type<EnumerationType>();
        modifyHtml() += i18n("enumeration %1 ", identifierHighlight(m_declaration->identifier().toString().toHtmlEscaped(), m_declaration));
      }

      if(m_declaration->isForwardDeclaration()) {
        ForwardDeclaration* forwardDec = static_cast<ForwardDeclaration*>(m_declaration.data());
        Declaration* resolved = forwardDec->resolve(m_topContext.data());
        if(resolved) {
          modifyHtml() += i18n("( resolved forward-declaration: ");
          makeLink(resolved->identifier().toString(), KDevelop::DeclarationPointer(resolved), NavigationAction::NavigateDeclaration );
          modifyHtml() += i18n(") ");
        }else{
          modifyHtml() += i18n("(unresolved forward-declaration) ");
          QualifiedIdentifier id = forwardDec->qualifiedIdentifier();
          uint count;
          const IndexedDeclaration* decls;
          PersistentSymbolTable::self().declarations(id, count, decls);
          for(uint a = 0; a < count; ++a) {
            if(decls[a].isValid() && !decls[a].data()->isForwardDeclaration()) {
              modifyHtml() += "<br />";
              makeLink(i18n("possible resolution from"), KDevelop::DeclarationPointer(decls[a].data()), NavigationAction::NavigateDeclaration);
              modifyHtml() += ' ' + decls[a].data()->url().str();
            }
          }
        }
      }
      modifyHtml() += "<br />";
    }
  }else{
    AbstractType::Ptr showType = m_declaration->abstractType();
    if(showType && showType.cast<FunctionType>()) {
      showType = showType.cast<FunctionType>()->returnType();
      if(showType)
        modifyHtml() += labelHighlight(i18n("Returns: "));
    }else  if(showType) {
      modifyHtml() += labelHighlight(i18n("Type: "));
    }
    
    if(showType) {
      eventuallyMakeTypeLinks(showType);
      modifyHtml() += " ";
    }
  }
  
  QualifiedIdentifier identifier = m_declaration->qualifiedIdentifier();
  if( identifier.count() > 1 ) {
    if( m_declaration->context() && m_declaration->context()->owner() )
    {
      Declaration* decl = m_declaration->context()->owner();

      FunctionDefinition* definition = dynamic_cast<FunctionDefinition*>(decl);
      if(definition && definition->declaration())
        decl = definition->declaration();

      if(decl->abstractType().cast<EnumerationType>())
        modifyHtml() += labelHighlight(i18n("Enum: "));
      else
        modifyHtml() += labelHighlight(i18n("Container: "));

      makeLink( declarationName(DeclarationPointer(decl)), DeclarationPointer(decl), NavigationAction::NavigateDeclaration );
      modifyHtml() += " ";
    } else {
      QualifiedIdentifier parent = identifier;
      parent.pop();
      modifyHtml() += labelHighlight(i18n("Scope: %1 ", typeHighlight(parent.toString().toHtmlEscaped())));
    }
  }
  
  if( shorten && !m_declaration->comment().isEmpty() ) {
    QString comment = QString::fromUtf8(m_declaration->comment());
    if( comment.length() > 60 ) {
      comment.truncate(60);
      comment += "...";
    }
    comment.replace('\n', " ");
    comment.replace("<br />", " ");
    comment.replace("<br/>", " ");
    modifyHtml() += commentHighlight(comment.toHtmlEscaped()) + "   ";
  }
  

  QString access = stringFromAccess(m_declaration);
  if( !access.isEmpty() )
    modifyHtml() += labelHighlight(i18n("Access: %1 ", propertyHighlight(access.toHtmlEscaped())));


  ///@todo Enumerations

  QString detailsHtml;
  QStringList details = declarationDetails(m_declaration);
  if( !details.isEmpty() ) {
    bool first = true;
    foreach( const QString &str, details ) {
      if( !first )
        detailsHtml += ", ";
      first = false;
      detailsHtml += propertyHighlight(str);
    }
  }
Beispiel #14
0
void TestIdentifier::testQualifiedIdentifier()
{
  QFETCH(QString, stringId);
  const QStringList list = stringId.split(QStringLiteral("::"), QString::SkipEmptyParts);

  QualifiedIdentifier id(stringId);
  QCOMPARE(id.isEmpty(), stringId.isEmpty());
  QCOMPARE(id, QualifiedIdentifier(stringId));
  QVERIFY(!(id != QualifiedIdentifier(stringId)));
  QCOMPARE(id, QualifiedIdentifier(stringId));
  if (list.size() == 1) {
    QCOMPARE(id, QualifiedIdentifier(Identifier(list.last())));
  } else if (list.isEmpty()) {
    QualifiedIdentifier empty{Identifier()};
    QCOMPARE(id, empty);
    QVERIFY(empty.isEmpty());
    QVERIFY(empty.inRepository());
  }
  QCOMPARE(id.toString(), stringId);
  QCOMPARE(id.toStringList(), list);
  QCOMPARE(id.top(), Identifier(list.isEmpty() ? QString() : list.last()));

  if (stringId.isEmpty()) {
    QVERIFY(id.inRepository());
    QVERIFY(QualifiedIdentifier(id).inRepository());
  }

  QualifiedIdentifier copy = id;
  QCOMPARE(copy, id);
  copy = copy;
  QCOMPARE(copy, id);
  copy = QualifiedIdentifier();
  QVERIFY(copy.isEmpty());
  copy = id;
  QCOMPARE(copy, id);

  IndexedQualifiedIdentifier indexedId(id);
  QVERIFY(indexedId == id);
  QCOMPARE(indexedId, IndexedQualifiedIdentifier(id));
  QCOMPARE(indexedId.isValid(), !stringId.isEmpty());
  QCOMPARE(indexedId.identifier(), id);
  IndexedQualifiedIdentifier indexedCopy = indexedId;
  QCOMPARE(indexedCopy, indexedId);
  indexedCopy = indexedCopy;
  QCOMPARE(indexedCopy, indexedId);
  indexedCopy = IndexedQualifiedIdentifier();
  QVERIFY(!indexedCopy.isValid());
  indexedCopy = indexedId;
  QCOMPARE(indexedCopy, indexedId);

  QualifiedIdentifier moved = std::move(id);
  QVERIFY(id.isEmpty());
  QCOMPARE(moved, copy);

  IndexedQualifiedIdentifier movedIndexed = std::move(indexedId);
  QVERIFY(indexedId.isEmpty());
  QCOMPARE(movedIndexed, indexedCopy);

  copy.clear();
  QVERIFY(copy.isEmpty());

  copy.push(moved);
  QCOMPARE(copy, moved);

  copy.push(Identifier(QStringLiteral("lalala")));
  QCOMPARE(copy.count(), moved.count() + 1);
}
void ContextBuilder::closePrefixContext(const QualifiedIdentifier& id) {
  if(id.count() < 2)
    return;
  closeContext();
}
void NamespaceAliasDeclaration::setImportIdentifier(const QualifiedIdentifier& id) {
  Q_ASSERT(!id.explicitlyGlobal());
  d_func_dynamic()->m_importIdentifier = id;
}