diff --git a/swift/extractor/infra/SwiftLocationExtractor.cpp b/swift/extractor/infra/SwiftLocationExtractor.cpp index 46bbae87837..a5134b714b0 100644 --- a/swift/extractor/infra/SwiftLocationExtractor.cpp +++ b/swift/extractor/infra/SwiftLocationExtractor.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -67,6 +68,13 @@ void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceMa locatableLabel); } +void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager, + const swift::KeyPathExpr::Component* component, + TrapLabel locatableLabel) { + attachLocation(sourceManager, component->getSourceRange().Start, component->getSourceRange().End, + locatableLabel); +} + void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager, swift::SourceLoc loc, TrapLabel locatableLabel) { diff --git a/swift/extractor/infra/SwiftLocationExtractor.h b/swift/extractor/infra/SwiftLocationExtractor.h index 8f5ada9ab9b..bcdce512dd8 100644 --- a/swift/extractor/infra/SwiftLocationExtractor.h +++ b/swift/extractor/infra/SwiftLocationExtractor.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -74,6 +75,10 @@ class SwiftLocationExtractor { swift::Token& token, TrapLabel locatableLabel); + void attachLocation(const swift::SourceManager& sourceManager, + const swift::KeyPathExpr::Component* component, + TrapLabel locatableLabel); + private: TrapLabel fetchFileLabel(const std::filesystem::path& file); TrapDomain& trap; diff --git a/swift/extractor/infra/SwiftTagTraits.h b/swift/extractor/infra/SwiftTagTraits.h index 343cd22b360..f8c66512f9c 100644 --- a/swift/extractor/infra/SwiftTagTraits.h +++ b/swift/extractor/infra/SwiftTagTraits.h @@ -58,6 +58,7 @@ MAP(swift::Stmt, StmtTag) MAP(swift::PoundAssertStmt, PoundAssertStmtTag) MAP(swift::Argument, ArgumentTag) +MAP(swift::KeyPathExpr::Component, KeyPathComponentTag) MAP(swift::Expr, ExprTag) MAP(swift::ErrorExpr, ErrorExprTag) MAP(swift::LiteralExpr, LiteralExprTag) diff --git a/swift/extractor/translators/ExprTranslator.cpp b/swift/extractor/translators/ExprTranslator.cpp index 44978f8c744..998d3b2ba65 100644 --- a/swift/extractor/translators/ExprTranslator.cpp +++ b/swift/extractor/translators/ExprTranslator.cpp @@ -378,10 +378,10 @@ codeql::MemberRefExpr ExprTranslator::translateMemberRefExpr(const swift::Member codeql::KeyPathExpr ExprTranslator::translateKeyPathExpr(const swift::KeyPathExpr& expr) { auto entry = createExprEntry(expr); - // TODO this should be completely redone, as we are using internal stuff here instead of - // extracting expr.getComponents() if (!expr.isObjC()) { - entry.parsed_path = dispatcher.fetchOptionalLabel(expr.getParsedPath()); + for (const auto& component : expr.getComponents()) { + entry.components.push_back(emitKeyPathComponent(component)); + } if (auto rootTypeRepr = expr.getRootType()) { auto keyPathType = expr.getType()->getAs(); assert(keyPathType && "KeyPathExpr must have BoundGenericClassType"); @@ -488,6 +488,26 @@ TrapLabel ExprTranslator::emitArgument(const swift::Argument& arg) return entry.id; } +TrapLabel ExprTranslator::emitKeyPathComponent( + const swift::KeyPathExpr::Component& component) { + auto entry = dispatcher.createUncachedEntry(component); + entry.kind = static_cast(component.getKind()); + if (auto subscript_args = component.getSubscriptArgs()) { + for (const auto& arg : *subscript_args) { + entry.subscript_arguments.push_back(emitArgument(arg)); + } + } + if (component.getKind() == swift::KeyPathExpr::Component::Kind::TupleElement) { + entry.tuple_index = static_cast(component.getTupleIndex()); + } + if (component.hasDeclRef()) { + entry.decl_ref = dispatcher.fetchLabel(component.getDeclRef().getDecl()); + } + entry.component_type = dispatcher.fetchLabel(component.getComponentType()); + dispatcher.emit(entry); + return entry.id; +} + void ExprTranslator::fillExplicitCastExpr(const swift::ExplicitCastExpr& expr, codeql::ExplicitCastExpr& entry) { entry.sub_expr = dispatcher.fetchLabel(expr.getSubExpr()); diff --git a/swift/extractor/translators/ExprTranslator.h b/swift/extractor/translators/ExprTranslator.h index 4c7f7de7741..335329334d4 100644 --- a/swift/extractor/translators/ExprTranslator.h +++ b/swift/extractor/translators/ExprTranslator.h @@ -121,6 +121,7 @@ class ExprTranslator : public AstTranslatorBase { void fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr, codeql::AbstractClosureExpr& entry); TrapLabel emitArgument(const swift::Argument& arg); + TrapLabel emitKeyPathComponent(const swift::KeyPathExpr::Component& expr); void fillExplicitCastExpr(const swift::ExplicitCastExpr& expr, codeql::ExplicitCastExpr& entry); void fillIdentityExpr(const swift::IdentityExpr& expr, codeql::IdentityExpr& entry); void fillAnyTryExpr(const swift::AnyTryExpr& expr, codeql::AnyTryExpr& entry); diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index c58d03ef518..e57e1d94884 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -7,6 +7,8 @@ ql/lib/codeql/swift/elements/DbLocation.qll 2b07fe465cc6ea0e876892d8312bedca35d2 ql/lib/codeql/swift/elements/DbLocationConstructor.qll 88366e22ba40eaaee097f413130117925dda488f1bcbd3989e301e86dd394df3 c61b32994d403a8c4f85c26251e24ffb8c6ea34dbbe935872d868ccbfb6c1ff6 ql/lib/codeql/swift/elements/DiagnosticsConstructor.qll 6a3e312f3ed57465747c672cbb6d615eca89f42586519221d2973ac3e2ab052c a010ef546f9ed2a75b812ee47db00110056b3076b1f939efa2addb000c327427 ql/lib/codeql/swift/elements/ErrorElement.qll e054242b883bcc7fe1e2ee844268325a0a0b83486d5c7b4e334c73a5f8bd1d9f ab0028bab8a9ed14c6b4bfe0f8a10e4768ea1e21f86b495258021ab9b8e65aeb +ql/lib/codeql/swift/elements/KeyPathComponent.qll bf568c6502ce9950a5a5e783abc60de47dd9b55e99e04b69142c587092fb1cad 17ca53568580cee53230d70f825261acfa5b2c433cc35cdd8f5db8837176c8ae +ql/lib/codeql/swift/elements/KeyPathComponentConstructor.qll fa5fdff92a996add9aa79c320df011bf40ed50f83166c3c745bdb6c45bd22bb3 7afdff6d42b73c6968c486697daa0bc8dacb11815544c65c32f7fe9be3b05d2f ql/lib/codeql/swift/elements/OtherAvailabilitySpecConstructor.qll fe03628ffbad9369e4b6bf325a58a3013b621090eecd9e01a76710e0d234d66a 0b7ffc7ed88d2b0da9aad86d83272daf124a4597c0fee1184f7d2f3511063afd ql/lib/codeql/swift/elements/PlatformVersionAvailabilitySpecConstructor.qll ce9cc9b15eff28cf0f9ef94f1d7a9dbfbbb2fb64c0053c2b537046784fcd6ee6 8b776cb89ec44704babbce7ac69efb534bf0925ca43f04e7a7dc795435404393 ql/lib/codeql/swift/elements/UnspecifiedElementConstructor.qll 0d179f8189f6268916f88c78a2665f8d4e78dc71e71b6229354677e915ac505d e8f5c313b7d8b0e93cee84151a5f080013d2ca502f3facbbde4cdb0889bc7f8e @@ -366,7 +368,7 @@ ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll 325e4c4481e9ac07acdc6 ql/lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll 0d1d2328a3b5e503a883e7e6d7efd0ca5e7f2633abead9e4c94a9f98ed3cb223 69bff81c1b9413949eacb9298d2efb718ea808e68364569a1090c9878c4af856 ql/lib/codeql/swift/elements/type/WeakStorageType.qll 7c07739cfc1459f068f24fef74838428128054adf611504d22532e4a156073e7 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996 ql/lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll d88b031ef44d6de14b3ddcff2eb47b53dbd11550c37250ff2edb42e5d21ec3e9 26d855c33492cf7a118e439f7baeed0e5425cfaf058b1dcc007eca7ed765c897 -ql/lib/codeql/swift/elements.qll 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40 +ql/lib/codeql/swift/elements.qll d4d76166fa8eb793973aa1c6862e0a4f9f44ca5ac364b0832f6edf4fd201110b d4d76166fa8eb793973aa1c6862e0a4f9f44ca5ac364b0832f6edf4fd201110b ql/lib/codeql/swift/generated/AstNode.qll 02ca56d82801f942ae6265c6079d92ccafdf6b532f6bcebd98a04029ddf696e4 6216fda240e45bd4302fa0cf0f08f5f945418b144659264cdda84622b0420aa2 ql/lib/codeql/swift/generated/AvailabilityInfo.qll 996a5cfadf7ca049122a1d1a1a9eb680d6a625ce28ede5504b172eabe7640fd2 4fe6e0325ff021a576fcd004730115ffaa60a2d9020420c7d4a1baa498067b60 ql/lib/codeql/swift/generated/AvailabilitySpec.qll fb1255f91bb5e41ad4e9c675a2efbc50d0fb366ea2de68ab7eebd177b0795309 144e0c2e7d6c62ecee43325f7f26dcf437881edf0b75cc1bc898c6c4b61fdeaf @@ -378,15 +380,16 @@ ql/lib/codeql/swift/generated/Diagnostics.qll d2ee2db55e932dcaee95fcc1164a51ffbe ql/lib/codeql/swift/generated/Element.qll 9caf84a1da2509f5b01a22d6597126c573ae63ec3e8c6af6fd6fcc7ead0b4e82 70deb2238509d5ed660369bf763c796065d92efd732469088cdf67f68bacd796 ql/lib/codeql/swift/generated/ErrorElement.qll 4b032abe8ffb71376a29c63e470a52943ace2527bf7b433c97a8bf716f9ad102 4f2b1be162a5c275e3264dbc51bf98bce8846d251be8490a0d4b16cbc85f630f ql/lib/codeql/swift/generated/File.qll f88c485883dd9b2b4a366080e098372912e03fb3177e5cae58aa4449c2b03399 0333c49e3a11c48e6146a7f492ee31ac022d80150fc3f8bfafc3c8f94d66ff76 +ql/lib/codeql/swift/generated/KeyPathComponent.qll 8b6efa9859c817cafc89f06b5ccf9c6e9762940ac45a40a15ffd5eff79b558c9 295a2acb65fadf9216bf8c032f3183dbe74afadb69b413947cd31ebe2f2269dd ql/lib/codeql/swift/generated/Locatable.qll bdc98b9fb7788f44a4bf7e487ee5bd329473409950a8e9f116d61995615ad849 0b36b4fe45e2aa195e4bb70c50ea95f32f141b8e01e5f23466c6427dd9ab88fb ql/lib/codeql/swift/generated/Location.qll 851766e474cdfdfa67da42e0031fc42dd60196ff5edd39d82f08d3e32deb84c1 b29b2c37672f5acff15f1d3c5727d902f193e51122327b31bd27ec5f877bca3b ql/lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 -ql/lib/codeql/swift/generated/ParentChild.qll 7d45d4e872e769f37a5b157ba422c48afe482552e44d94ff5f6a5a6449d672e7 6f7464ecd8ca04b6aa261139b36a162e5b0636237d514b8431ef4f97a1c603dc +ql/lib/codeql/swift/generated/ParentChild.qll 3998d73048297cf2df42176b0060c025e57d409d56f3fbfab9c202bd46c07b5e 425b01328baf38bd5e46403e11b25b0e17cd5bc40731dbf64a46e01604611e15 ql/lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0 ql/lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 -ql/lib/codeql/swift/generated/Raw.qll 60bce9edc4af395d7c64959e1fb8abd6d0a79ea4920417e978783c3d357ef087 69d97b1a3a7e32834057fb95e9015fadbae4358af4f76b7e0c646f254c62f0ad -ql/lib/codeql/swift/generated/Synth.qll af02e0b49fe7b488592687996cc74d9525d4e3fbc9d324820b310b356f4d2612 5c740a660721173e9e4e45eb701d373ca19ff14d61cdaea309b65871e0deea90 -ql/lib/codeql/swift/generated/SynthConstructors.qll a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 +ql/lib/codeql/swift/generated/Raw.qll 50c6dbe929161332d75450aa347d95936d61007e278638191162a8d8be01cb26 f09d782d996e3c43c5afd1997fddc35d96ee0615c2327df62101572134f067c4 +ql/lib/codeql/swift/generated/Synth.qll 1b60c8eab214c8f9a3a1fb39a8785979bc3d86f2615ba0a580c35e17fd496851 052940a87ffb32214b1b3c774bc643aa5d4f31c484d3121b4da384c2839cb10b +ql/lib/codeql/swift/generated/SynthConstructors.qll bb0c69cea79a06ec3cc0e176fc6e63cfe125107a45373e41083fc4de056133b8 bb0c69cea79a06ec3cc0e176fc6e63cfe125107a45373e41083fc4de056133b8 ql/lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 ql/lib/codeql/swift/generated/UnknownLocation.qll e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882 e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882 ql/lib/codeql/swift/generated/UnspecifiedElement.qll dbc6ca4018012977b26ca184a88044c55b0661e3998cd14d46295b62a8d69625 184c9a0ce18c2ac881943b0fb400613d1401ed1d5564f90716b6c310ba5afe71 @@ -502,7 +505,7 @@ ql/lib/codeql/swift/generated/expr/InterpolatedStringLiteralExpr.qll 35f79ec9d44 ql/lib/codeql/swift/generated/expr/IsExpr.qll b5ca50490cae8ac590b68a1a51b7039a54280d606b42c444808a04fa26c7e1b6 b5ca50490cae8ac590b68a1a51b7039a54280d606b42c444808a04fa26c7e1b6 ql/lib/codeql/swift/generated/expr/KeyPathApplicationExpr.qll 232e204a06b8fad3247040d47a1aa34c6736b764ab1ebca6c5dc74c3d4fc0c9b 6b823c483ee33cd6419f0a61a543cfce0cecfd0c90df72e60d01f5df8b3da3c0 ql/lib/codeql/swift/generated/expr/KeyPathDotExpr.qll ea73a462801fbe5e27b2f47bca4b39f6936d326d15d6de3f18b7afa6ace35878 ea73a462801fbe5e27b2f47bca4b39f6936d326d15d6de3f18b7afa6ace35878 -ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll e44b9d2a7a6c046d2e61b40192c878e37bd9391c03c8277d92dfba05d9040228 e32c4f6fc35f4e7ada95e82b8dd2cd3eb1912406d3604066f2d183f1311f8c0d +ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll d78eb3a2805f7a98b23b8cb16aa66308e7a131284b4cd148a96e0b8c600e1db3 9f05ace69b0de3cdd9e9a1a6aafeb4478cd15423d2fa9e818dd049ddb2adfeb9 ql/lib/codeql/swift/generated/expr/LazyInitializerExpr.qll d8e93dcfa7fa8a00005f30b4aaa426f50d5040db11bef0c3b56558419b6cc110 3ca7d7ca9e52a025c38d7605c509d6758a4d5ceb0543192074c901f5935d4453 ql/lib/codeql/swift/generated/expr/LinearFunctionExpr.qll cd4c31bed9d0beb09fdfc57069d28adb3a661c064d9c6f52bb250011d8e212a7 cd4c31bed9d0beb09fdfc57069d28adb3a661c064d9c6f52bb250011d8e212a7 ql/lib/codeql/swift/generated/expr/LinearFunctionExtractOriginalExpr.qll ee7d3e025815b5af392ffc006ec91e3150130f2bd708ab92dbe80f2efa9e6792 bcf9ed64cca2dcf5bb544f6347de3d6faa059a1900042a36555e11dfbe0a6013 @@ -661,6 +664,10 @@ ql/test/extractor-tests/generated/AvailabilityInfo/AvailabilityInfo_getSpec.ql 4 ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/Diagnostics/Diagnostics.ql 6a4a9480cc929381e0337b181e5ac519a7abc6d597ebe24fb6701acf79ced86f 199c5bf8bd38e161d989e0e4db1ea1d3ddcb4d7cf571afd9112ce3ed8d9b8d2a ql/test/extractor-tests/generated/File/File.ql 17a26e4f8aeaf3d4a38e6eb18f5d965cd62b63671b84edcd068808b4f3a999df 009a1338750bf95f715b303ac3e6a6e827c82aec2068299a97b0585ce76e9239 +ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.ql 3d34d994ab5d6fada0d8acfb0dc514ba5315f094cb0a94dadfef12afebed9496 82c4d91df2a32f46b7aedb6570fd4e63871f32317b2d3e8dd5d2a396dbd92254 +ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.ql 1f51b17a6f7fdd0a6559ce0b3d8ee408a3ccf441f13f7b94bfba14e73ad6e357 24fd64ad77942909ea82a309bb6f56081363beaa7f557547b5b3b199dd79a69b +ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.ql c062b22dd4f705db394a07b6d274dc019baaed619cbcc31eebda8e3583bcda97 48542483f9b3b2a5993036845a640711ef50c3b359202feedd69a9e1bd0b19b8 +ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.ql b7a60a79a6368f410298d6a00c9ccefae47875c540b668a924ebb37d331564a5 798760446f64d552669c87c5c377d41dcdbcbcdbcc20f9c4b58bd15248e3fb0b ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql 5c017af7e6b16ee68990eec12affe81eb114338bac4d445f4b231fe0f110eccc db86c828a892b0acd150a780914e7e48c280cad473d3680a453bdee03aee1e9d @@ -798,7 +805,10 @@ ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOU ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 -ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.ql 3eddbfac203a76910d234572f51092b097d4cc948f42843a4532e772853451ba 1d1cf6f11c8221de9f07a789af788a473915b0e714502561f60c4b1d4e6dcd1e +ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.ql ce38c747737e13f80a212576ae943f0a770fc87a15dabcb0d730515aeb530a3f a50138c47e61e9eab4131a03e1b3e065ed0fca1452c6a3d4f8f48a6124d445be +ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.ql 61d8d0f50c62e6bdf98005609861f6f4fd16e59c439706abf03ba27f87ed3cb1 403ee884bb83b7a4207993afbda7964e676f5f64923ce11e65a0cf8bd199e01d +ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.ql 992497671107be454ffe1f42b513a5bca37bd31849587ad55f6bd87d8ac5d4a7 b51109f0d9e5e6238d8ab9e67f24d435a873a7884308c4f01ec4ecad51ed031d ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 diff --git a/swift/ql/lib/codeql/swift/elements.qll b/swift/ql/lib/codeql/swift/elements.qll index 50303dd9a55..50561d6f706 100644 --- a/swift/ql/lib/codeql/swift/elements.qll +++ b/swift/ql/lib/codeql/swift/elements.qll @@ -10,6 +10,7 @@ import codeql.swift.elements.Diagnostics import codeql.swift.elements.Element import codeql.swift.elements.ErrorElement import codeql.swift.elements.File +import codeql.swift.elements.KeyPathComponent import codeql.swift.elements.Locatable import codeql.swift.elements.Location import codeql.swift.elements.OtherAvailabilitySpec diff --git a/swift/ql/lib/codeql/swift/elements/KeyPathComponent.qll b/swift/ql/lib/codeql/swift/elements/KeyPathComponent.qll new file mode 100644 index 00000000000..a3c90170f3f --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/KeyPathComponent.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.KeyPathComponent + +class KeyPathComponent extends Generated::KeyPathComponent { } diff --git a/swift/ql/lib/codeql/swift/elements/KeyPathComponentConstructor.qll b/swift/ql/lib/codeql/swift/elements/KeyPathComponentConstructor.qll new file mode 100644 index 00000000000..625177a7ce2 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/KeyPathComponentConstructor.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.Raw + +predicate constructKeyPathComponent(Raw::KeyPathComponent id) { any() } diff --git a/swift/ql/lib/codeql/swift/generated/KeyPathComponent.qll b/swift/ql/lib/codeql/swift/generated/KeyPathComponent.qll new file mode 100644 index 00000000000..55a38ef8894 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/KeyPathComponent.qll @@ -0,0 +1,120 @@ +// generated by codegen/codegen.py +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.expr.Argument +import codeql.swift.elements.AstNode +import codeql.swift.elements.type.Type +import codeql.swift.elements.decl.ValueDecl + +module Generated { + /** + * A component of a `KeyPathExpr`. + */ + class KeyPathComponent extends Synth::TKeyPathComponent, AstNode { + override string getAPrimaryQlClass() { result = "KeyPathComponent" } + + /** + * Gets the kind of key path component. + * + * This is 3 for properties, 4 for array and dictionary subscripts, 5 for optional forcing + * (`!`), 6 for optional chaining (`?`), 7 for implicit optional wrapping, 8 for `self`, + * and 9 for tuple element indexing. + * + * The following values should not appear: 0 for invalid components, 1 for unresolved + * properties, 2 for unresolved subscripts, 10 for #keyPath dictionary keys, and 11 for + * implicit IDE code completion data. + */ + int getKind() { + result = Synth::convertKeyPathComponentToRaw(this).(Raw::KeyPathComponent).getKind() + } + + /** + * Gets the `index`th argument to an array or dictionary subscript expression (0-based). + * + * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the + * behavior of both the `Immediate` and non-`Immediate` versions. + */ + Argument getImmediateSubscriptArgument(int index) { + result = + Synth::convertArgumentFromRaw(Synth::convertKeyPathComponentToRaw(this) + .(Raw::KeyPathComponent) + .getSubscriptArgument(index)) + } + + /** + * Gets the `index`th argument to an array or dictionary subscript expression (0-based). + */ + final Argument getSubscriptArgument(int index) { + result = getImmediateSubscriptArgument(index).resolve() + } + + /** + * Gets any of the arguments to an array or dictionary subscript expression. + */ + final Argument getASubscriptArgument() { result = getSubscriptArgument(_) } + + /** + * Gets the number of arguments to an array or dictionary subscript expression. + */ + final int getNumberOfSubscriptArguments() { + result = count(int i | exists(getSubscriptArgument(i))) + } + + /** + * Gets the tuple index of this key path component, if it exists. + */ + int getTupleIndex() { + result = Synth::convertKeyPathComponentToRaw(this).(Raw::KeyPathComponent).getTupleIndex() + } + + /** + * Holds if `getTupleIndex()` exists. + */ + final predicate hasTupleIndex() { exists(getTupleIndex()) } + + /** + * Gets the property or subscript operator, if it exists. + * + * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the + * behavior of both the `Immediate` and non-`Immediate` versions. + */ + ValueDecl getImmediateDeclRef() { + result = + Synth::convertValueDeclFromRaw(Synth::convertKeyPathComponentToRaw(this) + .(Raw::KeyPathComponent) + .getDeclRef()) + } + + /** + * Gets the property or subscript operator, if it exists. + */ + final ValueDecl getDeclRef() { result = getImmediateDeclRef().resolve() } + + /** + * Holds if `getDeclRef()` exists. + */ + final predicate hasDeclRef() { exists(getDeclRef()) } + + /** + * Gets the return type of this component application. + * + * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the + * behavior of both the `Immediate` and non-`Immediate` versions. + */ + Type getImmediateComponentType() { + result = + Synth::convertTypeFromRaw(Synth::convertKeyPathComponentToRaw(this) + .(Raw::KeyPathComponent) + .getComponentType()) + } + + /** + * Gets the return type of this component application. + * + * An optional-chaining component has a non-optional type to feed into the rest of the key + * path; an optional-wrapping component is inserted if required to produce an optional type + * as the final output. + */ + final Type getComponentType() { result = getImmediateComponentType().resolve() } + } +} diff --git a/swift/ql/lib/codeql/swift/generated/ParentChild.qll b/swift/ql/lib/codeql/swift/generated/ParentChild.qll index 4c5be119eff..93277d2587b 100644 --- a/swift/ql/lib/codeql/swift/generated/ParentChild.qll +++ b/swift/ql/lib/codeql/swift/generated/ParentChild.qll @@ -219,6 +219,26 @@ private module Impl { ) } + private Element getImmediateChildOfKeyPathComponent( + KeyPathComponent e, int index, string partialPredicateCall + ) { + exists(int b, int bAstNode, int n, int nSubscriptArgument | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + nSubscriptArgument = + n + 1 + max(int i | i = -1 or exists(e.getImmediateSubscriptArgument(i)) | i) and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + or + result = e.getImmediateSubscriptArgument(index - n) and + partialPredicateCall = "SubscriptArgument(" + (index - n).toString() + ")" + ) + ) + } + private Element getImmediateChildOfUnspecifiedElement( UnspecifiedElement e, int index, string partialPredicateCall ) { @@ -1443,12 +1463,12 @@ private module Impl { private Element getImmediateChildOfKeyPathExpr( KeyPathExpr e, int index, string partialPredicateCall ) { - exists(int b, int bExpr, int n, int nRoot, int nParsedPath | + exists(int b, int bExpr, int n, int nRoot, int nComponent | b = 0 and bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and n = bExpr and nRoot = n + 1 and - nParsedPath = nRoot + 1 and + nComponent = nRoot + 1 + max(int i | i = -1 or exists(e.getImmediateComponent(i)) | i) and ( none() or @@ -1456,9 +1476,8 @@ private module Impl { or index = n and result = e.getImmediateRoot() and partialPredicateCall = "Root()" or - index = nRoot and - result = e.getImmediateParsedPath() and - partialPredicateCall = "ParsedPath()" + result = e.getImmediateComponent(index - nRoot) and + partialPredicateCall = "Component(" + (index - nRoot).toString() + ")" ) ) } @@ -4830,6 +4849,8 @@ private module Impl { or result = getImmediateChildOfAvailabilityInfo(e, index, partialAccessor) or + result = getImmediateChildOfKeyPathComponent(e, index, partialAccessor) + or result = getImmediateChildOfUnspecifiedElement(e, index, partialAccessor) or result = getImmediateChildOfOtherAvailabilitySpec(e, index, partialAccessor) diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index b081700ead4..fa62aeec85e 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -134,6 +134,49 @@ module Raw { class AvailabilitySpec extends @availability_spec, AstNode { } + class KeyPathComponent extends @key_path_component, AstNode { + override string toString() { result = "KeyPathComponent" } + + /** + * Gets the kind of key path component. + * + * This is 3 for properties, 4 for array and dictionary subscripts, 5 for optional forcing + * (`!`), 6 for optional chaining (`?`), 7 for implicit optional wrapping, 8 for `self`, + * and 9 for tuple element indexing. + * + * The following values should not appear: 0 for invalid components, 1 for unresolved + * properties, 2 for unresolved subscripts, 10 for #keyPath dictionary keys, and 11 for + * implicit IDE code completion data. + */ + int getKind() { key_path_components(this, result, _) } + + /** + * Gets the `index`th argument to an array or dictionary subscript expression (0-based). + */ + Argument getSubscriptArgument(int index) { + key_path_component_subscript_arguments(this, index, result) + } + + /** + * Gets the tuple index of this key path component, if it exists. + */ + int getTupleIndex() { key_path_component_tuple_indices(this, result) } + + /** + * Gets the property or subscript operator, if it exists. + */ + ValueDecl getDeclRef() { key_path_component_decl_refs(this, result) } + + /** + * Gets the return type of this component application. + * + * An optional-chaining component has a non-optional type to feed into the rest of the key + * path; an optional-wrapping component is inserted if required to produce an optional type + * as the final output. + */ + Type getComponentType() { key_path_components(this, _, result) } + } + class UnspecifiedElement extends @unspecified_element, ErrorElement { override string toString() { result = "UnspecifiedElement" } @@ -981,9 +1024,9 @@ module Raw { TypeRepr getRoot() { key_path_expr_roots(this, result) } /** - * Gets the parsed path of this key path expression, if it exists. + * Gets the `index`th component of this key path expression (0-based). */ - Expr getParsedPath() { key_path_expr_parsed_paths(this, result) } + KeyPathComponent getComponent(int index) { key_path_expr_components(this, index, result) } } class LazyInitializerExpr extends @lazy_initializer_expr, Expr { diff --git a/swift/ql/lib/codeql/swift/generated/Synth.qll b/swift/ql/lib/codeql/swift/generated/Synth.qll index ee322626ad2..a30d1b2e695 100644 --- a/swift/ql/lib/codeql/swift/generated/Synth.qll +++ b/swift/ql/lib/codeql/swift/generated/Synth.qll @@ -10,6 +10,7 @@ module Synth { TDbFile(Raw::DbFile id) { constructDbFile(id) } or TDbLocation(Raw::DbLocation id) { constructDbLocation(id) } or TDiagnostics(Raw::Diagnostics id) { constructDiagnostics(id) } or + TKeyPathComponent(Raw::KeyPathComponent id) { constructKeyPathComponent(id) } or TOtherAvailabilitySpec(Raw::OtherAvailabilitySpec id) { constructOtherAvailabilitySpec(id) } or TPlatformVersionAvailabilitySpec(Raw::PlatformVersionAvailabilitySpec id) { constructPlatformVersionAvailabilitySpec(id) @@ -310,7 +311,7 @@ module Synth { class TAstNode = TAvailabilityInfo or TAvailabilitySpec or TCaseLabelItem or TConditionElement or TDecl or - TExpr or TPattern or TStmt or TStmtCondition or TTypeRepr; + TExpr or TKeyPathComponent or TPattern or TStmt or TStmtCondition or TTypeRepr; class TAvailabilitySpec = TOtherAvailabilitySpec or TPlatformVersionAvailabilitySpec; @@ -486,6 +487,9 @@ module Synth { cached TDiagnostics convertDiagnosticsFromRaw(Raw::Element e) { result = TDiagnostics(e) } + cached + TKeyPathComponent convertKeyPathComponentFromRaw(Raw::Element e) { result = TKeyPathComponent(e) } + cached TOtherAvailabilitySpec convertOtherAvailabilitySpecFromRaw(Raw::Element e) { result = TOtherAvailabilitySpec(e) @@ -1383,6 +1387,8 @@ module Synth { or result = convertExprFromRaw(e) or + result = convertKeyPathComponentFromRaw(e) + or result = convertPatternFromRaw(e) or result = convertStmtFromRaw(e) @@ -2146,6 +2152,9 @@ module Synth { cached Raw::Element convertDiagnosticsToRaw(TDiagnostics e) { e = TDiagnostics(result) } + cached + Raw::Element convertKeyPathComponentToRaw(TKeyPathComponent e) { e = TKeyPathComponent(result) } + cached Raw::Element convertOtherAvailabilitySpecToRaw(TOtherAvailabilitySpec e) { e = TOtherAvailabilitySpec(result) @@ -3041,6 +3050,8 @@ module Synth { or result = convertExprToRaw(e) or + result = convertKeyPathComponentToRaw(e) + or result = convertPatternToRaw(e) or result = convertStmtToRaw(e) diff --git a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll index 07a3d82ce88..2040fd1f7e5 100644 --- a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll +++ b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll @@ -4,6 +4,7 @@ import codeql.swift.elements.CommentConstructor import codeql.swift.elements.DbFileConstructor import codeql.swift.elements.DbLocationConstructor import codeql.swift.elements.DiagnosticsConstructor +import codeql.swift.elements.KeyPathComponentConstructor import codeql.swift.elements.OtherAvailabilitySpecConstructor import codeql.swift.elements.PlatformVersionAvailabilitySpecConstructor import codeql.swift.elements.UnspecifiedElementConstructor diff --git a/swift/ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll index cfb51609099..cdbd17a789d 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll @@ -2,9 +2,13 @@ private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw import codeql.swift.elements.expr.Expr +import codeql.swift.elements.KeyPathComponent import codeql.swift.elements.type.TypeRepr module Generated { + /** + * A key-path expression. + */ class KeyPathExpr extends Synth::TKeyPathExpr, Expr { override string getAPrimaryQlClass() { result = "KeyPathExpr" } @@ -32,26 +36,33 @@ module Generated { final predicate hasRoot() { exists(getRoot()) } /** - * Gets the parsed path of this key path expression, if it exists. + * Gets the `index`th component of this key path expression (0-based). * * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ - Expr getImmediateParsedPath() { + KeyPathComponent getImmediateComponent(int index) { result = - Synth::convertExprFromRaw(Synth::convertKeyPathExprToRaw(this) + Synth::convertKeyPathComponentFromRaw(Synth::convertKeyPathExprToRaw(this) .(Raw::KeyPathExpr) - .getParsedPath()) + .getComponent(index)) } /** - * Gets the parsed path of this key path expression, if it exists. + * Gets the `index`th component of this key path expression (0-based). */ - final Expr getParsedPath() { result = getImmediateParsedPath().resolve() } + final KeyPathComponent getComponent(int index) { + result = getImmediateComponent(index).resolve() + } /** - * Holds if `getParsedPath()` exists. + * Gets any of the components of this key path expression. */ - final predicate hasParsedPath() { exists(getParsedPath()) } + final KeyPathComponent getAComponent() { result = getComponent(_) } + + /** + * Gets the number of components of this key path expression. + */ + final int getNumberOfComponents() { result = count(int i | exists(getComponent(i))) } } } diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index e457bc35325..f937d9e6309 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -112,6 +112,7 @@ locations( | @condition_element | @decl | @expr +| @key_path_component | @pattern | @stmt | @stmt_condition @@ -173,6 +174,31 @@ availability_info_specs( | @platform_version_availability_spec ; +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + unspecified_elements( unique int id: @unspecified_element, string property: string ref, @@ -994,10 +1020,11 @@ key_path_expr_roots( //dir=expr int root: @type_repr_or_none ref ); -#keyset[id] -key_path_expr_parsed_paths( //dir=expr +#keyset[id, index] +key_path_expr_components( //dir=expr int id: @key_path_expr ref, - int parsed_path: @expr_or_none ref + int index: int ref, + int component: @key_path_component_or_none ref ); lazy_initializer_exprs( //dir=expr @@ -2497,6 +2524,11 @@ variadic_sequence_types( //dir=type | @unspecified_element ; +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + @location_or_none = @location | @unspecified_element diff --git a/swift/ql/test/extractor-tests/expressions/all.expected b/swift/ql/test/extractor-tests/expressions/all.expected index 7ae195d377d..43812382416 100644 --- a/swift/ql/test/extractor-tests/expressions/all.expected +++ b/swift/ql/test/extractor-tests/expressions/all.expected @@ -287,3 +287,13 @@ | expressions.swift:163:9:163:9 | >>(_:_:) | DeclRefExpr | | expressions.swift:163:9:163:9 | Int.Type | TypeExpr | | expressions.swift:163:12:163:12 | 0 | IntegerLiteralExpr | +| expressions.swift:176:12:176:17 | #keyPath(...) | KeyPathExpr | +| expressions.swift:177:18:177:26 | #keyPath(...) | KeyPathExpr | +| expressions.swift:177:25:177:25 | 0 | IntegerLiteralExpr | +| expressions.swift:178:19:178:38 | #keyPath(...) | KeyPathExpr | +| expressions.swift:178:35:178:35 | a | StringLiteralExpr | +| expressions.swift:179:16:179:35 | #keyPath(...) | KeyPathExpr | +| expressions.swift:180:16:180:26 | #keyPath(...) | KeyPathExpr | +| expressions.swift:181:20:181:30 | #keyPath(...) | KeyPathExpr | +| expressions.swift:182:11:182:16 | #keyPath(...) | KeyPathExpr | +| expressions.swift:183:20:183:32 | #keyPath(...) | KeyPathExpr | diff --git a/swift/ql/test/extractor-tests/expressions/expressions.swift b/swift/ql/test/extractor-tests/expressions/expressions.swift index 3e16c0be0ac..8a33e805e4e 100644 --- a/swift/ql/test/extractor-tests/expressions/expressions.swift +++ b/swift/ql/test/extractor-tests/expressions/expressions.swift @@ -162,3 +162,22 @@ func bitwise() { _ = 1 << 0 _ = 1 >> 0 } + +struct Bar { + var value : Int + var opt : Int? +} + +struct Foo { + var value : Int + var opt : Bar? +} + +let prop = \Foo.value +let arrElement = \[Int][0] +let dictElement = \[String : Int]["a"] +let optForce = \Optional.self! +let optChain = \Foo.opt?.opt +let optChainWrap = \Foo.opt?.value +let slf = \Int.self +let tupleElement = \(Int, Int).0 diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.expected b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.expected new file mode 100644 index 00000000000..90bfc4f4f2a --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.expected @@ -0,0 +1,14 @@ +| file://:0:0:0:0 | KeyPathComponent | getKind: | 7 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int? | +| key_path_expr.swift:11:17:11:17 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int | +| key_path_expr.swift:12:24:12:26 | KeyPathComponent | getKind: | 4 | getNumberOfSubscriptArguments: | 1 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int | +| key_path_expr.swift:13:34:13:38 | KeyPathComponent | getKind: | 4 | getNumberOfSubscriptArguments: | 1 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int? | +| key_path_expr.swift:14:31:14:31 | KeyPathComponent | getKind: | 5 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int | +| key_path_expr.swift:14:31:14:31 | KeyPathComponent | getKind: | 8 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int? | +| key_path_expr.swift:15:21:15:21 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Bar? | +| key_path_expr.swift:15:24:15:24 | KeyPathComponent | getKind: | 6 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Bar | +| key_path_expr.swift:15:26:15:26 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int? | +| key_path_expr.swift:16:25:16:25 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Bar? | +| key_path_expr.swift:16:28:16:28 | KeyPathComponent | getKind: | 6 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Bar | +| key_path_expr.swift:16:30:16:30 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int | +| key_path_expr.swift:17:16:17:16 | KeyPathComponent | getKind: | 8 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int | +| key_path_expr.swift:18:32:18:32 | KeyPathComponent | getKind: | 9 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | yes | hasDeclRef: | no | getComponentType: | Int | diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.ql b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.ql new file mode 100644 index 00000000000..a22f64c3108 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.ql @@ -0,0 +1,17 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from + KeyPathComponent x, int getKind, int getNumberOfSubscriptArguments, string hasTupleIndex, + string hasDeclRef, Type getComponentType +where + toBeTested(x) and + not x.isUnknown() and + getKind = x.getKind() and + getNumberOfSubscriptArguments = x.getNumberOfSubscriptArguments() and + (if x.hasTupleIndex() then hasTupleIndex = "yes" else hasTupleIndex = "no") and + (if x.hasDeclRef() then hasDeclRef = "yes" else hasDeclRef = "no") and + getComponentType = x.getComponentType() +select x, "getKind:", getKind, "getNumberOfSubscriptArguments:", getNumberOfSubscriptArguments, + "hasTupleIndex:", hasTupleIndex, "hasDeclRef:", hasDeclRef, "getComponentType:", getComponentType diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.expected b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.expected new file mode 100644 index 00000000000..74dc644cb80 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.expected @@ -0,0 +1,7 @@ +| key_path_expr.swift:11:17:11:17 | KeyPathComponent | key_path_expr.swift:7:9:7:9 | value | +| key_path_expr.swift:12:24:12:26 | KeyPathComponent | file://:0:0:0:0 | subscript ... | +| key_path_expr.swift:13:34:13:38 | KeyPathComponent | file://:0:0:0:0 | subscript ... | +| key_path_expr.swift:15:21:15:21 | KeyPathComponent | key_path_expr.swift:8:9:8:9 | opt | +| key_path_expr.swift:15:26:15:26 | KeyPathComponent | key_path_expr.swift:3:9:3:9 | opt | +| key_path_expr.swift:16:25:16:25 | KeyPathComponent | key_path_expr.swift:8:9:8:9 | opt | +| key_path_expr.swift:16:30:16:30 | KeyPathComponent | key_path_expr.swift:2:9:2:9 | value | diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.ql b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.ql new file mode 100644 index 00000000000..06c97828998 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from KeyPathComponent x +where toBeTested(x) and not x.isUnknown() +select x, x.getDeclRef() diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.expected b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.expected new file mode 100644 index 00000000000..c86fff6a006 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.expected @@ -0,0 +1,2 @@ +| key_path_expr.swift:12:24:12:26 | KeyPathComponent | 0 | key_path_expr.swift:12:25:12:25 | : 0 | +| key_path_expr.swift:13:34:13:38 | KeyPathComponent | 0 | key_path_expr.swift:13:35:13:35 | : a | diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.ql b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.ql new file mode 100644 index 00000000000..650da2190ef --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from KeyPathComponent x, int index +where toBeTested(x) and not x.isUnknown() +select x, index, x.getSubscriptArgument(index) diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.expected b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.expected new file mode 100644 index 00000000000..d4563136606 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.expected @@ -0,0 +1 @@ +| key_path_expr.swift:18:32:18:32 | KeyPathComponent | 0 | diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.ql b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.ql new file mode 100644 index 00000000000..8eb21c8a8b3 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from KeyPathComponent x +where toBeTested(x) and not x.isUnknown() +select x, x.getTupleIndex() diff --git a/swift/ql/test/extractor-tests/generated/KeyPathComponent/key_path_expr.swift b/swift/ql/test/extractor-tests/generated/KeyPathComponent/key_path_expr.swift new file mode 100644 index 00000000000..5e804726b86 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/KeyPathComponent/key_path_expr.swift @@ -0,0 +1,18 @@ +struct Bar { + var value : Int + var opt : Int? +} + +struct Foo { + var value : Int + var opt : Bar? +} + +let prop = \Foo.value +let arrElement = \[Int][0] +let dictElement = \[String : Int]["a"] +let optForce = \Optional.self! +let optChain = \Foo.opt?.opt +let optChainWrap = \Foo.opt?.value +let slf = \Int.self +let tupleElement = \(Int, Int).0 diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.expected b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.expected new file mode 100644 index 00000000000..68e4a6ed34d --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.expected @@ -0,0 +1,8 @@ +| key_path_expr.swift:11:12:11:17 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 | +| key_path_expr.swift:12:18:12:26 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 | +| key_path_expr.swift:13:19:13:38 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 | +| key_path_expr.swift:14:16:14:35 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 2 | +| key_path_expr.swift:15:16:15:26 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 3 | +| key_path_expr.swift:16:20:16:30 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 4 | +| key_path_expr.swift:17:11:17:16 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 | +| key_path_expr.swift:18:20:18:32 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 | diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.ql b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.ql new file mode 100644 index 00000000000..783f1904040 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.ql @@ -0,0 +1,12 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from KeyPathExpr x, string hasType, string hasRoot, int getNumberOfComponents +where + toBeTested(x) and + not x.isUnknown() and + (if x.hasType() then hasType = "yes" else hasType = "no") and + (if x.hasRoot() then hasRoot = "yes" else hasRoot = "no") and + getNumberOfComponents = x.getNumberOfComponents() +select x, "hasType:", hasType, "hasRoot:", hasRoot, "getNumberOfComponents:", getNumberOfComponents diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.expected b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.expected new file mode 100644 index 00000000000..673c01e775f --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.expected @@ -0,0 +1,14 @@ +| key_path_expr.swift:11:12:11:17 | #keyPath(...) | 0 | key_path_expr.swift:11:17:11:17 | KeyPathComponent | +| key_path_expr.swift:12:18:12:26 | #keyPath(...) | 0 | key_path_expr.swift:12:24:12:26 | KeyPathComponent | +| key_path_expr.swift:13:19:13:38 | #keyPath(...) | 0 | key_path_expr.swift:13:34:13:38 | KeyPathComponent | +| key_path_expr.swift:14:16:14:35 | #keyPath(...) | 0 | key_path_expr.swift:14:31:14:31 | KeyPathComponent | +| key_path_expr.swift:14:16:14:35 | #keyPath(...) | 1 | key_path_expr.swift:14:31:14:31 | KeyPathComponent | +| key_path_expr.swift:15:16:15:26 | #keyPath(...) | 0 | key_path_expr.swift:15:21:15:21 | KeyPathComponent | +| key_path_expr.swift:15:16:15:26 | #keyPath(...) | 1 | key_path_expr.swift:15:24:15:24 | KeyPathComponent | +| key_path_expr.swift:15:16:15:26 | #keyPath(...) | 2 | key_path_expr.swift:15:26:15:26 | KeyPathComponent | +| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 0 | key_path_expr.swift:16:25:16:25 | KeyPathComponent | +| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 1 | key_path_expr.swift:16:28:16:28 | KeyPathComponent | +| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 2 | key_path_expr.swift:16:30:16:30 | KeyPathComponent | +| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 3 | file://:0:0:0:0 | KeyPathComponent | +| key_path_expr.swift:17:11:17:16 | #keyPath(...) | 0 | key_path_expr.swift:17:16:17:16 | KeyPathComponent | +| key_path_expr.swift:18:20:18:32 | #keyPath(...) | 0 | key_path_expr.swift:18:32:18:32 | KeyPathComponent | diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.ql b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.ql new file mode 100644 index 00000000000..27a30ae6c7f --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from KeyPathExpr x, int index +where toBeTested(x) and not x.isUnknown() +select x, index, x.getComponent(index) diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.expected b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.expected new file mode 100644 index 00000000000..5e391528d7c --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.expected @@ -0,0 +1,8 @@ +| key_path_expr.swift:11:12:11:17 | #keyPath(...) | key_path_expr.swift:11:13:11:13 | Foo | +| key_path_expr.swift:12:18:12:26 | #keyPath(...) | key_path_expr.swift:12:19:12:23 | [Int] | +| key_path_expr.swift:13:19:13:38 | #keyPath(...) | key_path_expr.swift:13:20:13:33 | [String : Int] | +| key_path_expr.swift:14:16:14:35 | #keyPath(...) | key_path_expr.swift:14:17:14:29 | Int? | +| key_path_expr.swift:15:16:15:26 | #keyPath(...) | key_path_expr.swift:15:17:15:17 | Foo | +| key_path_expr.swift:16:20:16:30 | #keyPath(...) | key_path_expr.swift:16:21:16:21 | Foo | +| key_path_expr.swift:17:11:17:16 | #keyPath(...) | key_path_expr.swift:17:12:17:12 | Int | +| key_path_expr.swift:18:20:18:32 | #keyPath(...) | key_path_expr.swift:18:21:18:30 | (Int, Int) | diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.ql b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.ql new file mode 100644 index 00000000000..5ec9803da85 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from KeyPathExpr x +where toBeTested(x) and not x.isUnknown() +select x, x.getRoot() diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.expected b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.expected new file mode 100644 index 00000000000..cdf1ac3d9f8 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.expected @@ -0,0 +1,8 @@ +| key_path_expr.swift:11:12:11:17 | #keyPath(...) | WritableKeyPath | +| key_path_expr.swift:12:18:12:26 | #keyPath(...) | WritableKeyPath<[Int], Int> | +| key_path_expr.swift:13:19:13:38 | #keyPath(...) | WritableKeyPath<[String : Int], Int?> | +| key_path_expr.swift:14:16:14:35 | #keyPath(...) | WritableKeyPath | +| key_path_expr.swift:15:16:15:26 | #keyPath(...) | KeyPath | +| key_path_expr.swift:16:20:16:30 | #keyPath(...) | KeyPath | +| key_path_expr.swift:17:11:17:16 | #keyPath(...) | WritableKeyPath | +| key_path_expr.swift:18:20:18:32 | #keyPath(...) | WritableKeyPath<(Int, Int), Int> | diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.ql b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.ql new file mode 100644 index 00000000000..8743a0f0375 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from KeyPathExpr x +where toBeTested(x) and not x.isUnknown() +select x, x.getType() diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt deleted file mode 100644 index 25daf3d23a2..00000000000 --- a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt +++ /dev/null @@ -1,4 +0,0 @@ -// generated by codegen/codegen.py - -After a source file is added in this directory and codegen/codegen.py is run again, test queries -will appear and this file will be deleted diff --git a/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/key_path_expr.swift b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/key_path_expr.swift new file mode 100644 index 00000000000..5e804726b86 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/KeyPathExpr/key_path_expr.swift @@ -0,0 +1,18 @@ +struct Bar { + var value : Int + var opt : Int? +} + +struct Foo { + var value : Int + var opt : Bar? +} + +let prop = \Foo.value +let arrElement = \[Int][0] +let dictElement = \[String : Int]["a"] +let optForce = \Optional.self! +let optChain = \Foo.opt?.opt +let optChainWrap = \Foo.opt?.value +let slf = \Int.self +let tupleElement = \(Int, Int).0 diff --git a/swift/ql/test/library-tests/ast/PrintAst.expected b/swift/ql/test/library-tests/ast/PrintAst.expected index dc06c2810cd..162c9e60c4c 100644 --- a/swift/ql/test/library-tests/ast/PrintAst.expected +++ b/swift/ql/test/library-tests/ast/PrintAst.expected @@ -3005,24 +3005,38 @@ cfg.swift: # 456| getElement(0): [PatternBindingDecl] var ... = ... # 456| getInit(0): [KeyPathExpr] #keyPath(...) # 456| getRoot(): [TypeRepr] A +# 456| getComponent(0): [KeyPathComponent] KeyPathComponent +# 456| getComponent(1): [KeyPathComponent] KeyPathComponent # 456| getPattern(0): [NamedPattern] kpGet_b_x # 456| getElement(1): [ConcreteVarDecl] kpGet_b_x # 456| Type = WritableKeyPath # 457| getElement(2): [PatternBindingDecl] var ... = ... # 457| getInit(0): [KeyPathExpr] #keyPath(...) # 457| getRoot(): [TypeRepr] A +# 457| getComponent(0): [KeyPathComponent] KeyPathComponent +# 457| getComponent(1): [KeyPathComponent] KeyPathComponent +# 457| getSubscriptArgument(0): [Argument] : 0 +# 457| getExpr(): [IntegerLiteralExpr] 0 +# 457| getComponent(2): [KeyPathComponent] KeyPathComponent # 457| getPattern(0): [NamedPattern] kpGet_bs_0_x # 457| getElement(3): [ConcreteVarDecl] kpGet_bs_0_x # 457| Type = WritableKeyPath # 458| getElement(4): [PatternBindingDecl] var ... = ... # 458| getInit(0): [KeyPathExpr] #keyPath(...) # 458| getRoot(): [TypeRepr] A +# 458| getComponent(0): [KeyPathComponent] KeyPathComponent +# 458| getComponent(1): [KeyPathComponent] KeyPathComponent +# 458| getComponent(2): [KeyPathComponent] KeyPathComponent # 458| getPattern(0): [NamedPattern] kpGet_mayB_force_x # 458| getElement(5): [ConcreteVarDecl] kpGet_mayB_force_x # 458| Type = WritableKeyPath # 459| getElement(6): [PatternBindingDecl] var ... = ... # 459| getInit(0): [KeyPathExpr] #keyPath(...) # 459| getRoot(): [TypeRepr] A +# 459| getComponent(0): [KeyPathComponent] KeyPathComponent +# 459| getComponent(1): [KeyPathComponent] KeyPathComponent +# 459| getComponent(2): [KeyPathComponent] KeyPathComponent +#-----| getComponent(3): [KeyPathComponent] KeyPathComponent # 459| getPattern(0): [NamedPattern] kpGet_mayB_x # 459| getElement(7): [ConcreteVarDecl] kpGet_mayB_x # 459| Type = KeyPath @@ -4642,6 +4656,7 @@ expressions.swift: # 54| getDest(): [DiscardAssignmentExpr] _ # 54| getSource(): [KeyPathExpr] #keyPath(...) # 54| getRoot(): [TypeRepr] S +# 54| getComponent(0): [KeyPathComponent] KeyPathComponent # 56| [ConcreteFuncDecl] unsafeFunction(pointer:) # 56| InterfaceType = (UnsafePointer) -> () # 56| getParam(0): [ParamDecl] pointer @@ -5252,6 +5267,7 @@ expressions.swift: # 154| getKeyPath(): [DeclRefExpr] keyPathB # 154| getKeyPath(): [KeyPathExpr] #keyPath(...) # 154| getRoot(): [TypeRepr] B +# 154| getComponent(0): [KeyPathComponent] KeyPathComponent # 154| getPattern(0): [NamedPattern] nested_apply # 154| getElement(5): [ConcreteVarDecl] nested_apply # 154| Type = Int @@ -5322,6 +5338,244 @@ expressions.swift: # 163| getExpr(): [IntegerLiteralExpr] 1 # 163| getArgument(1): [Argument] : 0 # 163| getExpr(): [IntegerLiteralExpr] 0 +# 166| [StructDecl] Bar +# 167| getMember(0): [PatternBindingDecl] var ... = ... +# 167| getPattern(0): [TypedPattern] ... as ... +# 167| getSubPattern(): [NamedPattern] value +# 167| getTypeRepr(): [TypeRepr] Int +# 167| getMember(1): [ConcreteVarDecl] value +# 167| Type = Int +# 167| getAccessorDecl(0): [AccessorDecl] get +# 167| InterfaceType = (Bar) -> () -> Int +# 167| getSelfParam(): [ParamDecl] self +# 167| Type = Bar +# 167| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [ReturnStmt] return ... +#-----| getResult(): [MemberRefExpr] .value +#-----| getBase(): [DeclRefExpr] self +# 167| getAccessorDecl(1): [AccessorDecl] set +# 167| InterfaceType = (inout Bar) -> (Int) -> () +# 167| getSelfParam(): [ParamDecl] self +# 167| Type = Bar +# 167| getParam(0): [ParamDecl] value +# 167| Type = Int +# 167| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [AssignExpr] ... = ... +#-----| getDest(): [MemberRefExpr] .value +#-----| getBase(): [DeclRefExpr] self +#-----| getSource(): [DeclRefExpr] value +# 167| getAccessorDecl(2): [AccessorDecl] _modify +# 167| InterfaceType = (inout Bar) -> () -> () +# 167| getSelfParam(): [ParamDecl] self +# 167| Type = Bar +# 167| getBody(): [BraceStmt] { ... } +# 167| getElement(0): [YieldStmt] yield ... +#-----| getResult(0): [InOutExpr] &... +#-----| getSubExpr(): [MemberRefExpr] .value +#-----| getBase(): [DeclRefExpr] self +# 168| getMember(2): [PatternBindingDecl] var ... = ... +#-----| getInit(0): [NilLiteralExpr] nil +# 168| getPattern(0): [TypedPattern] ... as ... +# 168| getSubPattern(): [NamedPattern] opt +# 168| getTypeRepr(): [TypeRepr] Int? +# 168| getMember(3): [ConcreteVarDecl] opt +# 168| Type = Int? +# 168| getAccessorDecl(0): [AccessorDecl] get +# 168| InterfaceType = (Bar) -> () -> Int? +# 168| getSelfParam(): [ParamDecl] self +# 168| Type = Bar +# 168| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [ReturnStmt] return ... +#-----| getResult(): [MemberRefExpr] .opt +#-----| getBase(): [DeclRefExpr] self +# 168| getAccessorDecl(1): [AccessorDecl] set +# 168| InterfaceType = (inout Bar) -> (Int?) -> () +# 168| getSelfParam(): [ParamDecl] self +# 168| Type = Bar +# 168| getParam(0): [ParamDecl] value +# 168| Type = Int? +# 168| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [AssignExpr] ... = ... +#-----| getDest(): [MemberRefExpr] .opt +#-----| getBase(): [DeclRefExpr] self +#-----| getSource(): [DeclRefExpr] value +# 168| getAccessorDecl(2): [AccessorDecl] _modify +# 168| InterfaceType = (inout Bar) -> () -> () +# 168| getSelfParam(): [ParamDecl] self +# 168| Type = Bar +# 168| getBody(): [BraceStmt] { ... } +# 168| getElement(0): [YieldStmt] yield ... +#-----| getResult(0): [InOutExpr] &... +#-----| getSubExpr(): [MemberRefExpr] .opt +#-----| getBase(): [DeclRefExpr] self +# 166| getMember(4): [ConstructorDecl] Bar.init(value:opt:) +# 166| InterfaceType = (Bar.Type) -> (Int, Int?) -> Bar +# 166| getSelfParam(): [ParamDecl] self +# 166| Type = Bar +# 166| getParam(0): [ParamDecl] value +# 166| Type = Int +# 166| getParam(1): [ParamDecl] opt +# 166| Type = Int? +# 171| [StructDecl] Foo +# 172| getMember(0): [PatternBindingDecl] var ... = ... +# 172| getPattern(0): [TypedPattern] ... as ... +# 172| getSubPattern(): [NamedPattern] value +# 172| getTypeRepr(): [TypeRepr] Int +# 172| getMember(1): [ConcreteVarDecl] value +# 172| Type = Int +# 172| getAccessorDecl(0): [AccessorDecl] get +# 172| InterfaceType = (Foo) -> () -> Int +# 172| getSelfParam(): [ParamDecl] self +# 172| Type = Foo +# 172| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [ReturnStmt] return ... +#-----| getResult(): [MemberRefExpr] .value +#-----| getBase(): [DeclRefExpr] self +# 172| getAccessorDecl(1): [AccessorDecl] set +# 172| InterfaceType = (inout Foo) -> (Int) -> () +# 172| getSelfParam(): [ParamDecl] self +# 172| Type = Foo +# 172| getParam(0): [ParamDecl] value +# 172| Type = Int +# 172| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [AssignExpr] ... = ... +#-----| getDest(): [MemberRefExpr] .value +#-----| getBase(): [DeclRefExpr] self +#-----| getSource(): [DeclRefExpr] value +# 172| getAccessorDecl(2): [AccessorDecl] _modify +# 172| InterfaceType = (inout Foo) -> () -> () +# 172| getSelfParam(): [ParamDecl] self +# 172| Type = Foo +# 172| getBody(): [BraceStmt] { ... } +# 172| getElement(0): [YieldStmt] yield ... +#-----| getResult(0): [InOutExpr] &... +#-----| getSubExpr(): [MemberRefExpr] .value +#-----| getBase(): [DeclRefExpr] self +# 173| getMember(2): [PatternBindingDecl] var ... = ... +#-----| getInit(0): [NilLiteralExpr] nil +# 173| getPattern(0): [TypedPattern] ... as ... +# 173| getSubPattern(): [NamedPattern] opt +# 173| getTypeRepr(): [TypeRepr] Bar? +# 173| getMember(3): [ConcreteVarDecl] opt +# 173| Type = Bar? +# 173| getAccessorDecl(0): [AccessorDecl] get +# 173| InterfaceType = (Foo) -> () -> Bar? +# 173| getSelfParam(): [ParamDecl] self +# 173| Type = Foo +# 173| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [ReturnStmt] return ... +#-----| getResult(): [MemberRefExpr] .opt +#-----| getBase(): [DeclRefExpr] self +# 173| getAccessorDecl(1): [AccessorDecl] set +# 173| InterfaceType = (inout Foo) -> (Bar?) -> () +# 173| getSelfParam(): [ParamDecl] self +# 173| Type = Foo +# 173| getParam(0): [ParamDecl] value +# 173| Type = Bar? +# 173| getBody(): [BraceStmt] { ... } +#-----| getElement(0): [AssignExpr] ... = ... +#-----| getDest(): [MemberRefExpr] .opt +#-----| getBase(): [DeclRefExpr] self +#-----| getSource(): [DeclRefExpr] value +# 173| getAccessorDecl(2): [AccessorDecl] _modify +# 173| InterfaceType = (inout Foo) -> () -> () +# 173| getSelfParam(): [ParamDecl] self +# 173| Type = Foo +# 173| getBody(): [BraceStmt] { ... } +# 173| getElement(0): [YieldStmt] yield ... +#-----| getResult(0): [InOutExpr] &... +#-----| getSubExpr(): [MemberRefExpr] .opt +#-----| getBase(): [DeclRefExpr] self +# 171| getMember(4): [ConstructorDecl] Foo.init(value:opt:) +# 171| InterfaceType = (Foo.Type) -> (Int, Bar?) -> Foo +# 171| getSelfParam(): [ParamDecl] self +# 171| Type = Foo +# 171| getParam(0): [ParamDecl] value +# 171| Type = Int +# 171| getParam(1): [ParamDecl] opt +# 171| Type = Bar? +# 176| [TopLevelCodeDecl] { ... } +# 176| getBody(): [BraceStmt] { ... } +# 176| getElement(0): [PatternBindingDecl] var ... = ... +# 176| getInit(0): [KeyPathExpr] #keyPath(...) +# 176| getRoot(): [TypeRepr] Foo +# 176| getComponent(0): [KeyPathComponent] KeyPathComponent +# 176| getPattern(0): [NamedPattern] prop +# 176| [ConcreteVarDecl] prop +# 176| Type = WritableKeyPath +# 177| [TopLevelCodeDecl] { ... } +# 177| getBody(): [BraceStmt] { ... } +# 177| getElement(0): [PatternBindingDecl] var ... = ... +# 177| getInit(0): [KeyPathExpr] #keyPath(...) +# 177| getRoot(): [TypeRepr] [Int] +# 177| getComponent(0): [KeyPathComponent] KeyPathComponent +# 177| getSubscriptArgument(0): [Argument] : 0 +# 177| getExpr(): [IntegerLiteralExpr] 0 +# 177| getPattern(0): [NamedPattern] arrElement +# 177| [ConcreteVarDecl] arrElement +# 177| Type = WritableKeyPath<[Int], Int> +# 178| [TopLevelCodeDecl] { ... } +# 178| getBody(): [BraceStmt] { ... } +# 178| getElement(0): [PatternBindingDecl] var ... = ... +# 178| getInit(0): [KeyPathExpr] #keyPath(...) +# 178| getRoot(): [TypeRepr] [String : Int] +# 178| getComponent(0): [KeyPathComponent] KeyPathComponent +# 178| getSubscriptArgument(0): [Argument] : a +# 178| getExpr(): [StringLiteralExpr] a +# 178| getPattern(0): [NamedPattern] dictElement +# 178| [ConcreteVarDecl] dictElement +# 178| Type = WritableKeyPath<[String : Int], Int?> +# 179| [TopLevelCodeDecl] { ... } +# 179| getBody(): [BraceStmt] { ... } +# 179| getElement(0): [PatternBindingDecl] var ... = ... +# 179| getInit(0): [KeyPathExpr] #keyPath(...) +# 179| getRoot(): [TypeRepr] Int? +# 179| getComponent(0): [KeyPathComponent] KeyPathComponent +# 179| getComponent(1): [KeyPathComponent] KeyPathComponent +# 179| getPattern(0): [NamedPattern] optForce +# 179| [ConcreteVarDecl] optForce +# 179| Type = WritableKeyPath +# 180| [TopLevelCodeDecl] { ... } +# 180| getBody(): [BraceStmt] { ... } +# 180| getElement(0): [PatternBindingDecl] var ... = ... +# 180| getInit(0): [KeyPathExpr] #keyPath(...) +# 180| getRoot(): [TypeRepr] Foo +# 180| getComponent(0): [KeyPathComponent] KeyPathComponent +# 180| getComponent(1): [KeyPathComponent] KeyPathComponent +# 180| getComponent(2): [KeyPathComponent] KeyPathComponent +# 180| getPattern(0): [NamedPattern] optChain +# 180| [ConcreteVarDecl] optChain +# 180| Type = KeyPath +# 181| [TopLevelCodeDecl] { ... } +# 181| getBody(): [BraceStmt] { ... } +# 181| getElement(0): [PatternBindingDecl] var ... = ... +# 181| getInit(0): [KeyPathExpr] #keyPath(...) +# 181| getRoot(): [TypeRepr] Foo +# 181| getComponent(0): [KeyPathComponent] KeyPathComponent +# 181| getComponent(1): [KeyPathComponent] KeyPathComponent +# 181| getComponent(2): [KeyPathComponent] KeyPathComponent +#-----| getComponent(3): [KeyPathComponent] KeyPathComponent +# 181| getPattern(0): [NamedPattern] optChainWrap +# 181| [ConcreteVarDecl] optChainWrap +# 181| Type = KeyPath +# 182| [TopLevelCodeDecl] { ... } +# 182| getBody(): [BraceStmt] { ... } +# 182| getElement(0): [PatternBindingDecl] var ... = ... +# 182| getInit(0): [KeyPathExpr] #keyPath(...) +# 182| getRoot(): [TypeRepr] Int +# 182| getComponent(0): [KeyPathComponent] KeyPathComponent +# 182| getPattern(0): [NamedPattern] slf +# 182| [ConcreteVarDecl] slf +# 182| Type = WritableKeyPath +# 183| [TopLevelCodeDecl] { ... } +# 183| getBody(): [BraceStmt] { ... } +# 183| getElement(0): [PatternBindingDecl] var ... = ... +# 183| getInit(0): [KeyPathExpr] #keyPath(...) +# 183| getRoot(): [TypeRepr] (Int, Int) +# 183| getComponent(0): [KeyPathComponent] KeyPathComponent +# 183| getPattern(0): [NamedPattern] tupleElement +# 183| [ConcreteVarDecl] tupleElement +# 183| Type = WritableKeyPath<(Int, Int), Int> patterns.swift: # 1| [ConcreteFuncDecl] basic_patterns() # 1| InterfaceType = () -> () diff --git a/swift/ql/test/library-tests/ast/expressions.swift b/swift/ql/test/library-tests/ast/expressions.swift index 3e16c0be0ac..8a33e805e4e 100644 --- a/swift/ql/test/library-tests/ast/expressions.swift +++ b/swift/ql/test/library-tests/ast/expressions.swift @@ -162,3 +162,22 @@ func bitwise() { _ = 1 << 0 _ = 1 >> 0 } + +struct Bar { + var value : Int + var opt : Int? +} + +struct Foo { + var value : Int + var opt : Bar? +} + +let prop = \Foo.value +let arrElement = \[Int][0] +let dictElement = \[String : Int]["a"] +let optForce = \Optional.self! +let optChain = \Foo.opt?.opt +let optChainWrap = \Foo.opt?.value +let slf = \Int.self +let tupleElement = \(Int, Int).0 diff --git a/swift/schema.py b/swift/schema.py index 828525627bd..8f7d4a95c6e 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -449,9 +449,36 @@ class KeyPathApplicationExpr(Expr): class KeyPathDotExpr(Expr): pass +class KeyPathComponent(AstNode): + """ + A component of a `KeyPathExpr`. + """ + kind: int | doc("kind of key path component") | desc(""" + This is 3 for properties, 4 for array and dictionary subscripts, 5 for optional forcing + (`!`), 6 for optional chaining (`?`), 7 for implicit optional wrapping, 8 for `self`, + and 9 for tuple element indexing. + + The following values should not appear: 0 for invalid components, 1 for unresolved + properties, 2 for unresolved subscripts, 10 for #keyPath dictionary keys, and 11 for + implicit IDE code completion data. + """) + subscript_arguments : list[Argument] | child | doc( + "arguments to an array or dictionary subscript expression") + tuple_index : optional[int] + decl_ref : optional[ValueDecl] | doc("property or subscript operator") + component_type : Type | doc("return type of this component application") | desc(""" + An optional-chaining component has a non-optional type to feed into the rest of the key + path; an optional-wrapping component is inserted if required to produce an optional type + as the final output. + """) + + class KeyPathExpr(Expr): + """ + A key-path expression. + """ root: optional["TypeRepr"] | child - parsed_path: optional[Expr] | child + components: list[KeyPathComponent] | child class LazyInitializerExpr(Expr): sub_expr: Expr | child