Swift: Extract structured keypath components.

Changes in swift/ql/lib are generated by swift/codegen without manual intervention.
This commit is contained in:
Alexandre Boulgakov
2023-04-06 18:26:14 +01:00
parent 2b1dea56b5
commit 35a2d55d18
40 changed files with 821 additions and 34 deletions

View File

@@ -1,3 +1,4 @@
#include <swift/AST/Expr.h>
#include <swift/AST/SourceFile.h>
#include <swift/Basic/SourceManager.h>
#include <swift/Parse/Token.h>
@@ -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<LocatableTag> locatableLabel) {
attachLocation(sourceManager, component->getSourceRange().Start, component->getSourceRange().End,
locatableLabel);
}
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
swift::SourceLoc loc,
TrapLabel<LocatableTag> locatableLabel) {

View File

@@ -2,6 +2,7 @@
#include <swift/AST/ASTAllocated.h>
#include <swift/AST/AvailabilitySpec.h>
#include <swift/AST/Expr.h>
#include <swift/AST/SourceFile.h>
#include <swift/Basic/SourceManager.h>
#include <unordered_map>
@@ -74,6 +75,10 @@ class SwiftLocationExtractor {
swift::Token& token,
TrapLabel<LocatableTag> locatableLabel);
void attachLocation(const swift::SourceManager& sourceManager,
const swift::KeyPathExpr::Component* component,
TrapLabel<LocatableTag> locatableLabel);
private:
TrapLabel<FileTag> fetchFileLabel(const std::filesystem::path& file);
TrapDomain& trap;

View File

@@ -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)

View File

@@ -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<swift::BoundGenericClassType>();
assert(keyPathType && "KeyPathExpr must have BoundGenericClassType");
@@ -488,6 +488,26 @@ TrapLabel<ArgumentTag> ExprTranslator::emitArgument(const swift::Argument& arg)
return entry.id;
}
TrapLabel<KeyPathComponentTag> ExprTranslator::emitKeyPathComponent(
const swift::KeyPathExpr::Component& component) {
auto entry = dispatcher.createUncachedEntry(component);
entry.kind = static_cast<int>(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<int>(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());

View File

@@ -121,6 +121,7 @@ class ExprTranslator : public AstTranslatorBase<ExprTranslator> {
void fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr,
codeql::AbstractClosureExpr& entry);
TrapLabel<ArgumentTag> emitArgument(const swift::Argument& arg);
TrapLabel<KeyPathComponentTag> 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);

View File

@@ -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

View File

@@ -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

View File

@@ -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 { }

View File

@@ -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() }

View File

@@ -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() }
}
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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

View File

@@ -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))) }
}
}

View File

@@ -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

View File

@@ -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 |

View File

@@ -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<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -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 |

View File

@@ -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

View File

@@ -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 |

View File

@@ -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()

View File

@@ -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 |

View File

@@ -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)

View File

@@ -0,0 +1 @@
| key_path_expr.swift:18:32:18:32 | KeyPathComponent | 0 |

View File

@@ -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()

View File

@@ -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<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -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 |

View File

@@ -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

View File

@@ -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 |

View File

@@ -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)

View File

@@ -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) |

View File

@@ -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()

View File

@@ -0,0 +1,8 @@
| key_path_expr.swift:11:12:11:17 | #keyPath(...) | WritableKeyPath<Foo, Int> |
| 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<Int?, Int> |
| key_path_expr.swift:15:16:15:26 | #keyPath(...) | KeyPath<Foo, Int?> |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | KeyPath<Foo, Int?> |
| key_path_expr.swift:17:11:17:16 | #keyPath(...) | WritableKeyPath<Int, Int> |
| key_path_expr.swift:18:20:18:32 | #keyPath(...) | WritableKeyPath<(Int, Int), Int> |

View File

@@ -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()

View File

@@ -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

View File

@@ -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<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -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<A, Int>
# 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<A, Int>
# 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<A, Int>
# 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<A, Int?>
@@ -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<Int>) -> ()
# 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<Foo, Int>
# 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<Int?, Int>
# 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<Foo, Int?>
# 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<Foo, Int?>
# 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<Int, Int>
# 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 = () -> ()

View File

@@ -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<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -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