diff --git a/duchain/builders/declarationbuilder.cpp b/duchain/builders/declarationbuilder.cpp --- a/duchain/builders/declarationbuilder.cpp +++ b/duchain/builders/declarationbuilder.cpp @@ -833,9 +833,18 @@ funDec->addDefaultParameter(IndexedString(symbol)); if (node->isVariadic != -1) { reportError(i18n("Variadic parameter cannot have a default value"), node->defaultValue); - } else if (node->parameterType && node->parameterType->typehint && isClassTypehint(node->parameterType->typehint, m_editor) - && symbol.compare(QLatin1String("null"), Qt::CaseInsensitive) != 0 ) { + } else if (node->parameterType && node->parameterType->typehint && isClassTypehint(node->parameterType->typehint, m_editor) && + symbol.compare(QLatin1String("null"), Qt::CaseInsensitive) != 0) { reportError(i18n("Default value for parameters with a class type hint can only be NULL."), node->defaultValue); + } else if (node->parameterType && node->parameterType->typehint && node->parameterType->typehint->genericType && + symbol.compare(QLatin1String("null"), Qt::CaseInsensitive) != 0) { + NamespacedIdentifierAst* typehintNode = node->parameterType->typehint->genericType; + const KDevPG::ListNode< IdentifierAst* >* it = typehintNode->namespaceNameSequence->back(); + QString typehintName = m_editor->parseSession()->symbol(it->element); + + if (typehintName.compare(QLatin1String("object"), Qt::CaseInsensitive) == 0) { + reportError(i18n("Default value for parameters with an object type can only be NULL."), node->defaultValue); + } } } else { funDec->addDefaultParameter(IndexedString{}); @@ -1617,6 +1626,7 @@ || className.compare(QLatin1String("int"), Qt::CaseInsensitive) == 0 || className.compare(QLatin1String("float"), Qt::CaseInsensitive) == 0 || className.compare(QLatin1String("iterable"), Qt::CaseInsensitive) == 0 + || className.compare(QLatin1String("object"), Qt::CaseInsensitive) == 0 || className.compare(QLatin1String("null"), Qt::CaseInsensitive) == 0 || className.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0 || className.compare(QLatin1String("false"), Qt::CaseInsensitive) == 0; diff --git a/duchain/builders/typebuilder.cpp b/duchain/builders/typebuilder.cpp --- a/duchain/builders/typebuilder.cpp +++ b/duchain/builders/typebuilder.cpp @@ -86,7 +86,7 @@ } } else { if (!type.compare(QLatin1String("object"), Qt::CaseInsensitive)) { - type = QStringLiteral("stdclass"); + return AbstractType::Ptr(new IntegralTypeExtended(IntegralTypeExtended::TypeObject)); } //don't use openTypeFromName as it uses cursor for findDeclarations DeclarationPointer decl = findDeclarationImport(ClassDeclarationType, diff --git a/duchain/helper.cpp b/duchain/helper.cpp --- a/duchain/helper.cpp +++ b/duchain/helper.cpp @@ -109,6 +109,8 @@ return false; } else if (typehint.compare(QLatin1String("iterable"), Qt::CaseInsensitive) == 0) { return false; + } else if (typehint.compare(QLatin1String("object"), Qt::CaseInsensitive) == 0) { + return false; } else { return true; } @@ -479,6 +481,8 @@ type = AbstractType::Ptr(new IntegralType(IntegralType::TypeInt)); } else if (typehint.compare(QLatin1String("string"), Qt::CaseInsensitive) == 0) { type = AbstractType::Ptr(new IntegralType(IntegralType::TypeString)); + } else if (typehint.compare(QLatin1String("object"), Qt::CaseInsensitive) == 0) { + type = AbstractType::Ptr(new IntegralTypeExtended(IntegralTypeExtended::TypeObject)); } else if (typehint.compare(QLatin1String("iterable"), Qt::CaseInsensitive) == 0) { DeclarationPointer traversableDecl = findDeclarationImportHelper(currentContext, QualifiedIdentifier("traversable"), ClassDeclarationType); diff --git a/duchain/tests/duchain.h b/duchain/tests/duchain.h --- a/duchain/tests/duchain.h +++ b/duchain/tests/duchain.h @@ -44,6 +44,7 @@ void declareTypehintFunction(); void declareVariadicFunction(); void declareTypehintVariadicFunction(); + void declareTypehintObjectFunction(); void declareTypehintArrayFunction(); void declareTypehintCallableFunction(); void functionWithCallableAndFunctionReturn(); @@ -66,6 +67,7 @@ void declarationReturnTypeClassChain(); void declarationReturnTypeTypehint(); void declarationReturnTypeTypehintVoid(); + void declarationReturnTypeTypehintObject(); void classImplementsInterface(); void classExtends(); void staticMethod(); diff --git a/duchain/tests/duchain.cpp b/duchain/tests/duchain.cpp --- a/duchain/tests/duchain.cpp +++ b/duchain/tests/duchain.cpp @@ -667,8 +667,8 @@ dec = top->localDeclarations().at(3); fType = dec->type(); QVERIFY(fType); - QVERIFY(StructureType::Ptr::dynamicCast(fType->returnType())); - QCOMPARE(StructureType::Ptr::dynamicCast(fType->returnType())->qualifiedIdentifier(), QualifiedIdentifier("stdclass")); + QVERIFY(IntegralTypeExtended::Ptr::dynamicCast(fType->returnType())); + QVERIFY(IntegralTypeExtended::Ptr::dynamicCast(fType->returnType())->dataType() == IntegralTypeExtended::TypeObject); //test hint in internal functions file of a type that is added later on // function @@ -781,6 +781,26 @@ QVERIFY(returnType->dataType() == IntegralType::TypeVoid); } +void TestDUChain::declarationReturnTypeTypehintObject() +{ + //Typehint preferred over phpdoc preferred over inferred type + QByteArray method("parentContext()); + QCOMPARE(top->childContexts().count(), 2); + QCOMPARE(top->localDeclarations().count(), 1); + + FunctionType::Ptr fun = top->localDeclarations().first()->type(); + QVERIFY(fun); + IntegralTypeExtended::Ptr returnType = IntegralTypeExtended::Ptr::dynamicCast(fun->returnType()); + QVERIFY(returnType); + QVERIFY(returnType->dataType() == IntegralTypeExtended::TypeObject); +} + void TestDUChain::declareTypehintFunction() { // 0 1 2 3 4 5 6 7 @@ -877,6 +897,28 @@ QCOMPARE(typehint->toString(), QStringLiteral("A")); } +void TestDUChain::declareTypehintObjectFunction() +{ + // 0 1 2 3 4 5 6 7 + // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 + QByteArray method("localDeclarations().first()->type(); + QVERIFY(fun); + QCOMPARE(fun->arguments().count(), 1); + QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())); + QVERIFY(IntegralType::Ptr::dynamicCast(fun->arguments().first())->dataType() == IntegralTypeExtended::TypeObject); + + IntegralTypeExtended::Ptr type = top->childContexts().first()->localDeclarations().first()->type(); + QVERIFY(type); + QVERIFY(type->dataType() == IntegralTypeExtended::TypeObject); +} + void TestDUChain::declareTypehintArrayFunction() { // 0 1 2 3 4 5 6 7 diff --git a/duchain/types/integraltypeextended.h b/duchain/types/integraltypeextended.h --- a/duchain/types/integraltypeextended.h +++ b/duchain/types/integraltypeextended.h @@ -41,7 +41,8 @@ enum PHPIntegralTypes { TypeResource = KDevelop::IntegralType::TypeLanguageSpecific, - TypeCallable + TypeCallable, + TypeObject }; /// Default constructor diff --git a/duchain/types/integraltypeextended.cpp b/duchain/types/integraltypeextended.cpp --- a/duchain/types/integraltypeextended.cpp +++ b/duchain/types/integraltypeextended.cpp @@ -53,6 +53,8 @@ return QStringLiteral("resource"); } else if (d_func()->m_dataType == TypeCallable) { return QStringLiteral("callable"); + } else if (d_func()->m_dataType == TypeObject) { + return QStringLiteral("object"); } return KDevelop::IntegralType::toString(); }