Esempio n. 1
0
bool ExpressionVisitor::encounterParent(const QString& declaration)
{
    if (declaration != QLatin1String("parent") ||
        !QmlJS::isQmlFile(m_context)) {
        return false;
    }

    // Go up until we find a class context (the enclosing QML component)
    const DUContext* parent = m_context;
    Declaration* owner;

    while (parent && parent->type() != DUContext::Class) {
        parent = parent->parentContext();
    }

    // Take the parent context of the current QML component, it is its parent
    // component
    if (parent) {
        parent = parent->parentContext();
    }

    // Parent now points to the parent QML component. This is not always what
    // the user wants when typing "parent", but already works well for
    // "anchors.centerIn: parent" and things like that.
    if (parent &&
        (owner = QmlJS::getOwnerOfContext(parent)) &&
        owner->abstractType()) {
        encounterLvalue(DeclarationPointer(owner));
        instantiateCurrentDeclaration();
        return true;
    }

    return false;
}
Esempio n. 2
0
bool ExpressionVisitor::visit(QmlJS::AST::ThisExpression* node)
{
    Q_UNUSED(node)
    DUChainReadLocker lock;
    DUContext* paramsContext;
    DUContext* internalContext;
    Declaration* owner;

    // "this" points to the current function (not semantically valid in JS,
    // but this allows ExpressionVisitor to see the declarations of the
    // function's prototype)
    if (m_context->type() == DUContext::Other &&                // Code of the function
        (paramsContext = m_context->parentContext()) &&         // Parameters of the function (this context has the function as owner)
        (owner = QmlJS::getOwnerOfContext(paramsContext)) &&    // The function itself (owner of its parameters)
        (internalContext = QmlJS::getInternalContext(DeclarationPointer(owner))) && // The prototype context of the function
        (owner = QmlJS::getOwnerOfContext(internalContext)) &&  // The function that declared the prototype context (paramsContext may belong to a method of a class)
        owner->abstractType()) {
        encounterLvalue(DeclarationPointer(owner));
        instantiateCurrentDeclaration();
    } else {
        encounterNothing();
    }

    return false;
}
Esempio n. 3
0
QString DUChainItemData::text() const
{
  DUChainReadLocker lock;;
  Declaration* decl = m_item.m_item.data();
  if(!decl)
    return i18n("Not available any more: %1", m_item.m_text);

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

  QString text = decl->qualifiedIdentifier().toString();

  if(!decl->abstractType()) {
    //With simplified representation, still mark functions as such by adding parens
    if(dynamic_cast<AbstractFunctionDeclaration*>(decl)) {
      text += QLatin1String("(...)");
    }
  }else if(TypePtr<FunctionType> function = decl->type<FunctionType>()) {
    text += function->partToString( FunctionType::SignatureArguments );
  }

  return text;
}
Esempio n. 4
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();
}
Esempio n. 5
0
void TestDUChainMultipleFiles::testForeachImportedIdentifier()
{
    // see https://bugs.kde.org/show_bug.cgi?id=269369

    TopDUContext::Features features = TopDUContext::VisibleDeclarationsAndContexts;

    TestProject* project = new TestProject;
    m_projectController->clearProjects();
    m_projectController->addProject(project);

    // build dependency
    TestFile f1("<? class SomeIterator implements Countable, Iterator { }", "php", project);
    f1.parse(features);
    f1.waitForParsed();

    TestFile f2("<?\n"
                "class A {\n"
                "  public function foo() { $i = $this->bar(); foreach($i as $a => $b) {} } \n"
                "  public function bar() { $a = new SomeIterator(); return $a; }\n"
                " }\n", "php", project);

    for(int i = 0; i < 2; ++i) {
        if (i > 0) {
            features = static_cast<TopDUContext::Features>(features | TopDUContext::ForceUpdate);
        }
        f2.parse(features);
        f2.waitForParsed();
        QTest::qWait(100);

        DUChainWriteLocker lock(DUChain::lock());
        DUContext* ACtx = f2.topContext()->childContexts().first();
        QVERIFY(ACtx);
        Declaration* iDec = ACtx->childContexts().at(1)->localDeclarations().first();
        QVERIFY(iDec);
        Declaration* SomeIteratorDec = f1.topContext()->localDeclarations().first();
        QVERIFY(SomeIteratorDec);
        if (i == 0) {
            QEXPECT_FAIL("", "needs a full two-pass (i.e. get rid of PreDeclarationBuilder)", Continue);
        }
        QVERIFY(iDec->abstractType()->equals(SomeIteratorDec->abstractType().constData()));
        QVERIFY(f2.topContext()->imports(f1.topContext(), CursorInRevision(0, 0)));
    }
}
Esempio n. 6
0
void ExpressionVisitor::encounterObjectAtLocation(const QmlJS::AST::SourceLocation& location)
{
    DUChainReadLocker lock;

    // Find the anonymous declaration corresponding to the function. This is
    // the owner of the current context (function expressions create new contexts)
    Declaration* dec = QmlJS::getOwnerOfContext(m_context->topContext()->findContextAt(
        CursorInRevision(location.startLine-1, location.startColumn)
    ));

    if (dec && dec->abstractType()) {
        encounterLvalue(DeclarationPointer(dec));
    } else {
        encounterNothing();
    }
}
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);
    }
  }
Esempio n. 8
0
void AliasDeclaration::setAliasedDeclaration(const IndexedDeclaration& decl) {
  d_func_dynamic()->m_aliasedDeclaration = decl;
  Declaration* aliased = decl.data();
  if(aliased)
    Declaration::setAbstractType(aliased->abstractType());
}