File indexing completed on 2024-05-12 04:38:43
0001 /* 0002 SPDX-FileCopyrightText: 2012 Olivier de Gaalon <olivier.jg@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #ifndef KDEVPLATFORM_JSONDECLARATIONTESTS_H 0008 #define KDEVPLATFORM_JSONDECLARATIONTESTS_H 0009 0010 #include "language/duchain/ducontext.h" 0011 #include "language/duchain/declaration.h" 0012 #include "language/duchain/indexeddeclaration.h" 0013 #include "language/duchain/identifier.h" 0014 #include "language/duchain/abstractfunctiondeclaration.h" 0015 #include "language/duchain/types/typeutils.h" 0016 #include "language/duchain/types/identifiedtype.h" 0017 #include <language/duchain/types/functiontype.h> 0018 #include "language/duchain/duchain.h" 0019 #include "language/duchain/functiondefinition.h" 0020 #include "language/duchain/definitions.h" 0021 #include <language/duchain/classfunctiondeclaration.h> 0022 #include "jsontesthelpers.h" 0023 0024 /** 0025 * JSON Object Specification: 0026 * DeclTestObject: Mapping of (string) declaration test names to values 0027 * TypeTestObject: Mapping of (string) type test names to values 0028 * CtxtTestObject: Mapping of (string) context test names to values 0029 * 0030 * Quick Reference: 0031 * useCount : int 0032 * useRanges : string array 0033 * identifier : string 0034 * qualifiedIdentifier : string 0035 * internalContext : CtxtTestObject 0036 * internalFunctionContext : CtxtTestObject 0037 * type : TypeTestObject 0038 * unaliasedType : TypeTestObject 0039 * targetType : TypeTestObject 0040 * returnType : TypeTestObject 0041 * isAtomic : bool 0042 * isAbstract : bool 0043 * isMutable : bool 0044 * isVirtual : bool 0045 * isStatic : bool 0046 * declaration : DeclTestObject 0047 * definition : DeclTestObject 0048 * identifiedTypeDeclaration : DeclTestObject 0049 * null : bool 0050 * defaultParameter : string 0051 * toString : string 0052 * range : string 0053 * kind : string 0054 * isDeprecated : bool 0055 * isDefinition : bool 0056 * isExplicitlyTyped : bool 0057 */ 0058 0059 namespace KDevelop { 0060 template<> 0061 QString TestSuite<Declaration*>::objectInformation(Declaration* decl) 0062 { 0063 VERIFY_NOT_NULL(decl); 0064 return QStringLiteral("(Declaration on line %1 in %2)") 0065 .arg(decl->range().start.line + 1) 0066 .arg(decl->topContext()->url().str()); 0067 } 0068 0069 namespace DeclarationTests { 0070 using namespace JsonTestHelpers; 0071 0072 ///JSON type: int 0073 ///@returns whether the declaration's number of uses matches the given value 0074 DeclarationTest(useCount) 0075 { 0076 int uses = 0; 0077 const auto declarationUses = decl->uses(); 0078 for (const auto& useRanges : declarationUses) { 0079 uses += useRanges.size(); 0080 } 0081 0082 return compareValues(uses, value, QStringLiteral("Declaration's use count ")); 0083 } 0084 ///JSON type: string array 0085 ///@returns whether the declaration's ranges match the given value 0086 DeclarationTest(useRanges) 0087 { 0088 QStringList ranges; 0089 const auto declarationUses = decl->uses(); 0090 for (const auto& useRanges : declarationUses) { 0091 for (const RangeInRevision range : useRanges) { 0092 ranges << rangeStr(range); 0093 } 0094 } 0095 0096 const QStringList testValues = value.toStringList(); 0097 return ranges == testValues ? SUCCESS() 0098 : QStringLiteral("Declaration's use ranges (\"%1\") don't match test data (\"%2\").").arg(ranges.join( 0099 QStringLiteral( 0100 ", ")), 0101 testValues.join( 0102 QStringLiteral( 0103 ", "))); 0104 } 0105 ///JSON type: string 0106 ///@returns whether the declaration's identifier matches the given value 0107 DeclarationTest(identifier) 0108 { 0109 VERIFY_NOT_NULL(decl); 0110 return compareValues(decl->identifier().toString(), value, QStringLiteral("Declaration's identifier")); 0111 } 0112 ///JSON type: string 0113 ///@returns whether the declaration's qualified identifier matches the given value 0114 DeclarationTest(qualifiedIdentifier) 0115 { 0116 VERIFY_NOT_NULL(decl); 0117 return compareValues(decl->qualifiedIdentifier().toString(), value, 0118 QStringLiteral("Declaration's qualified identifier")); 0119 } 0120 ///JSON type: CtxtTestObject 0121 ///@returns whether the tests for the declaration's internal context pass 0122 DeclarationTest(internalContext) 0123 { 0124 VERIFY_NOT_NULL(decl); 0125 return testObject(decl->internalContext(), value, QStringLiteral("Declaration's internal context")); 0126 } 0127 ///JSON type: CtxtTestObject 0128 ///@returns whether the tests for the declaration's internal function context pass 0129 DeclarationTest(internalFunctionContext) 0130 { 0131 const QString NO_INTERNAL_CTXT = QStringLiteral("%1 has no internal function context."); 0132 auto* absFuncDecl = dynamic_cast<AbstractFunctionDeclaration*>(decl); 0133 if (!absFuncDecl || !absFuncDecl->internalFunctionContext()) 0134 return NO_INTERNAL_CTXT.arg(decl->qualifiedIdentifier().toString()); 0135 return testObject(absFuncDecl->internalFunctionContext(), value, 0136 QStringLiteral("Declaration's internal function context")); 0137 } 0138 /*FIXME: The type functions need some renaming and moving around 0139 * Some (all?) functions from cpp's TypeUtils should be moved to the kdevplatform type utils 0140 * targetType is exactly like realType except it also tosses pointers 0141 * shortenTypeForViewing should go to type utils (and it's broken, it places const to the left of all *'s when it should be left or right of the type) 0142 * UnaliasedType seems to be unable to understand aliases involving templates, perhaps a cpp version is in order 0143 */ 0144 ///JSON type: TypeTestObject 0145 ///@returns whether the tests for the declaration's type pass 0146 DeclarationTest(type) 0147 { 0148 VERIFY_NOT_NULL(decl); 0149 return testObject(decl->abstractType(), value, QStringLiteral("Declaration's type")); 0150 } 0151 ///JSON type: TypeTestObject 0152 ///@returns whether the tests for the declaration's unaliased type pass (TypeUtils::unaliasedType) 0153 DeclarationTest(unaliasedType) 0154 { 0155 VERIFY_NOT_NULL(decl); 0156 return testObject(TypeUtils::unAliasedType(decl->abstractType()), value, 0157 QStringLiteral("Declaration's unaliased type")); 0158 } 0159 ///JSON type: TypeTestObject 0160 ///@returns whether the tests for the declaration's target type pass (TypeUtils::targetType) 0161 DeclarationTest(targetType) 0162 { 0163 VERIFY_NOT_NULL(decl); 0164 return testObject(TypeUtils::targetType(decl->abstractType(), decl->topContext()), value, 0165 QStringLiteral("Declaration's target type")); 0166 } 0167 ///JSON type: TestTypeObject 0168 ///@returns the 0169 DeclarationTest(returnType) 0170 { 0171 AbstractType::Ptr returnType; 0172 if (auto functionType = decl->abstractType().dynamicCast<FunctionType>()) { 0173 returnType = functionType->returnType(); 0174 } 0175 return testObject(returnType, value, QStringLiteral("Declaration's return type")); 0176 } 0177 ///JSON type: DeclTestObject 0178 ///@returns The IdentifiedType's declaration 0179 DeclarationTest(identifiedTypeDeclaration) 0180 { 0181 const QString UN_ID_ERROR = QStringLiteral("Unable to identify declaration of type \"%1\"."); 0182 AbstractType::Ptr type = TypeUtils::targetType(decl->abstractType(), decl->topContext()); 0183 auto* idType = dynamic_cast<IdentifiedType*>(type.data()); 0184 Declaration* idDecl = idType ? idType->declaration(decl->topContext()) : nullptr; 0185 if (!idDecl) 0186 return UN_ID_ERROR.arg(type->toString()); 0187 0188 return testObject(idDecl, value, QStringLiteral("IdentifiedType's declaration")); 0189 } 0190 0191 ///JSON type: bool 0192 ///@returns whether the declaration's isAtomic matches the given value 0193 DeclarationTest(isAtomic) 0194 { 0195 AbstractType::Ptr type = TypeUtils::targetType(decl->abstractType(), decl->topContext()); 0196 0197 return compareValues((type->modifiers() & AbstractType::AtomicModifier) != 0, value, QStringLiteral("Declaration's atomic modifier")); 0198 } 0199 0200 ///JSON type: bool 0201 ///@returns whether the (function) declaration's isVirtual matches the given value 0202 DeclarationTest(isVirtual) 0203 { 0204 const QString NOT_A_FUNCTION = QStringLiteral("Non-function declaration cannot be virtual."); 0205 auto* absFuncDecl = dynamic_cast<AbstractFunctionDeclaration*>(decl); 0206 if (!absFuncDecl) 0207 return NOT_A_FUNCTION; 0208 0209 return compareValues(absFuncDecl->isVirtual(), value, QStringLiteral("Declaration's isVirtual")); 0210 } 0211 0212 ///JSON type: bool 0213 ///@returns whether the (function) declaration's isAbstract matches the given value 0214 DeclarationTest(isAbstract) 0215 { 0216 const QString NOT_A_FUNCTION = QStringLiteral("Non-class-function declaration cannot be abstract."); 0217 auto* absFuncDecl = dynamic_cast<ClassFunctionDeclaration*>(decl); 0218 if (!absFuncDecl) 0219 return NOT_A_FUNCTION; 0220 0221 return compareValues(absFuncDecl->isAbstract(), value, QStringLiteral("Declaration's isAbstract")); 0222 } 0223 ///JSON type: bool 0224 ///@returns whether the (function) declaration's isAbstract matches the given value 0225 DeclarationTest(isFinal) 0226 { 0227 const QString NOT_A_FUNCTION = QStringLiteral("Non-class-function declaration cannot be final."); 0228 auto* classFuncDecl = dynamic_cast<ClassFunctionDeclaration*>(decl); 0229 if (!classFuncDecl) 0230 return NOT_A_FUNCTION; 0231 0232 return compareValues(classFuncDecl->isFinal(), value, QStringLiteral("Declaration's isFinal")); 0233 } 0234 ///JSON type: bool 0235 ///@returns whether the (class-member) declaration's isStatic matches the given value 0236 DeclarationTest(isStatic) 0237 { 0238 const QString NOT_A_MEMBER = QStringLiteral("Non-class-member declaration cannot be static."); 0239 auto memberDecl = dynamic_cast<ClassMemberDeclaration*>(decl); 0240 if (!memberDecl) 0241 return NOT_A_MEMBER; 0242 0243 return compareValues(memberDecl->isStatic(), value, QStringLiteral("Declaration's isStatic")); 0244 } 0245 ///JSON type: bool 0246 ///@returns whether the (class-member) declaration's isMutable matches the given value 0247 DeclarationTest(isMutable) 0248 { 0249 const QString NOT_A_MEMBER = QStringLiteral("Non-class-member declaration cannot be mutable."); 0250 auto memberDecl = dynamic_cast<ClassMemberDeclaration*>(decl); 0251 if (!memberDecl) 0252 return NOT_A_MEMBER; 0253 0254 return compareValues(memberDecl->isMutable(), value, QStringLiteral("Declaration's isMutable")); 0255 } 0256 ///JSON type: DeclTestObject 0257 ///@returns whether the tests for the function declaration's definition pass 0258 DeclarationTest(definition) 0259 { 0260 KDevVarLengthArray<IndexedDeclaration> definitions = DUChain::definitions()->definitions(decl->id()); 0261 Declaration* declDef = nullptr; 0262 if (!definitions.isEmpty()) 0263 declDef = definitions.at(0).declaration(); 0264 return testObject(declDef, value, QStringLiteral("Declaration's definition")); 0265 } 0266 ///JSON type: DeclTestObject 0267 ///@returns whether the tests for the function definition's declaration pass 0268 DeclarationTest(declaration) 0269 { 0270 auto* def = dynamic_cast<FunctionDefinition*>(decl); 0271 Declaration* defDecl = nullptr; 0272 if (def) 0273 defDecl = def->declaration(decl->topContext()); 0274 return testObject(defDecl, value, QStringLiteral("Definition's declaration")); 0275 } 0276 ///JSON type: bool 0277 ///@returns whether the declaration's nullity matches the given value 0278 DeclarationTest(null) 0279 { 0280 return compareValues(decl == nullptr, value, QStringLiteral("Declaration's nullity")); 0281 } 0282 ///JSON type: bool 0283 ///@returns whether the declaration's default parameter matches the given value 0284 DeclarationTest(defaultParameter) 0285 { 0286 const QString NOT_IN_FUNC_CTXT = QStringLiteral( 0287 "Asked for a default parameter for a declaration outside of a function context."); 0288 const QString OWNER_NOT_FUNC = QStringLiteral( 0289 "Function context not owned by function declaration (what on earth did you do?)."); 0290 DUContext* context = decl->context(); 0291 if (!context || context->type() != DUContext::Function) 0292 return NOT_IN_FUNC_CTXT; 0293 auto* funcDecl = dynamic_cast<AbstractFunctionDeclaration*>(context->owner()); 0294 if (!funcDecl) 0295 return OWNER_NOT_FUNC; 0296 int argIndex = context->localDeclarations().indexOf(decl); 0297 return compareValues(funcDecl->defaultParameterForArgument(argIndex).str(), value, 0298 QStringLiteral("Declaration's default parameter")); 0299 } 0300 0301 ///JSON type: string 0302 ///@returns stringified declaration 0303 DeclarationTest(toString) 0304 { 0305 VERIFY_NOT_NULL(decl); 0306 return compareValues(decl->toString(), value, QStringLiteral("Declaration's toString")); 0307 } 0308 0309 ///JSON type: string 0310 ///@returns stringified declaration range 0311 DeclarationTest(range) 0312 { 0313 VERIFY_NOT_NULL(decl); 0314 return compareValues(rangeStr(decl->range()), value, QStringLiteral("Declaration's range")); 0315 } 0316 0317 ///JSON type: string 0318 ///@returns stringified declaration kind 0319 DeclarationTest(kind) 0320 { 0321 VERIFY_NOT_NULL(decl); 0322 QString kind; 0323 switch (decl->kind()) { 0324 case KDevelop::Declaration::Alias: 0325 kind = QStringLiteral("Alias"); 0326 break; 0327 case KDevelop::Declaration::Import: 0328 kind = QStringLiteral("Import"); 0329 break; 0330 case KDevelop::Declaration::Instance: 0331 kind = QStringLiteral("Instance"); 0332 break; 0333 case KDevelop::Declaration::Namespace: 0334 kind = QStringLiteral("Namespace"); 0335 break; 0336 case KDevelop::Declaration::NamespaceAlias: 0337 kind = QStringLiteral("NamespaceAlias"); 0338 break; 0339 case KDevelop::Declaration::Type: 0340 kind = QStringLiteral("Type"); 0341 break; 0342 case KDevelop::Declaration::Macro: 0343 kind = QStringLiteral("Macro"); 0344 break; 0345 } 0346 return compareValues(kind, value, QStringLiteral("Declaration's kind")); 0347 } 0348 0349 ///JSON type: bool 0350 ///@returns whether the declaration's isDeprecated matches the given value 0351 DeclarationTest(isDeprecated) 0352 { 0353 VERIFY_NOT_NULL(decl); 0354 return compareValues(decl->isDeprecated(), value, QStringLiteral("Declaration's isDeprecated")); 0355 } 0356 0357 ///JSON type: bool 0358 ///@returns whether the declaration's isDefinition matches the given value 0359 DeclarationTest(isDefinition) 0360 { 0361 VERIFY_NOT_NULL(decl); 0362 return compareValues(decl->isDefinition(), value, QStringLiteral("Declaration's isDefinition")); 0363 } 0364 0365 ///JSON type: bool 0366 ///@returns whether the declaration's isExplicitlyTyped matches the given value 0367 DeclarationTest(isExplicitlyTyped) 0368 { 0369 VERIFY_NOT_NULL(decl); 0370 return compareValues(decl->isExplicitlyTyped(), value, QStringLiteral("Declaration's isExplicitlyTyped")); 0371 } 0372 } 0373 } 0374 0375 #endif //KDEVPLATFORM_JSONDECLARATIONTESTS_H