@@ -46,18 +46,14 @@ func isExprMigrated(_ node: ExprSyntax) -> Bool {
4646 . discardAssignmentExpr, . declReferenceExpr, . dictionaryExpr, . doExpr,
4747 . editorPlaceholderExpr, . floatLiteralExpr, . forceUnwrapExpr, . functionCallExpr,
4848 . genericSpecializationExpr, . ifExpr, . infixOperatorExpr, . inOutExpr,
49- . integerLiteralExpr, . isExpr, . macroExpansionExpr, . memberAccessExpr, . nilLiteralExpr,
49+ . integerLiteralExpr, . isExpr, . keyPathExpr , . macroExpansionExpr, . memberAccessExpr, . nilLiteralExpr,
5050 . optionalChainingExpr, . packElementExpr, . packExpansionExpr, . patternExpr, . postfixIfConfigExpr,
5151 . postfixOperatorExpr, . prefixOperatorExpr, . regexLiteralExpr, . sequenceExpr,
5252 . simpleStringLiteralExpr, . subscriptCallExpr, . stringLiteralExpr, . superExpr,
5353 . switchExpr, . tryExpr, . tupleExpr, . typeExpr, . unresolvedAsExpr, . unresolvedIsExpr,
5454 . unresolvedTernaryExpr, . ternaryExpr:
5555 break
5656
57- // Known unimplemented kinds.
58- case . keyPathExpr:
59- return false
60-
6157 // Unknown expr kinds.
6258 case _ where current. is ( ExprSyntax . self) :
6359 return false
@@ -129,8 +125,8 @@ extension ASTGenVisitor {
129125 return self . generate ( integerLiteralExpr: node) . asExpr
130126 case . isExpr:
131127 preconditionFailure ( " IsExprSyntax only appear after operator folding " )
132- case . keyPathExpr:
133- break
128+ case . keyPathExpr( let node ) :
129+ return self . generate ( keyPathExpr : node )
134130 case . macroExpansionExpr( let node) :
135131 return self . generate ( macroExpansionExpr: node) . asExpr
136132 case . memberAccessExpr( let node) :
@@ -535,6 +531,118 @@ extension ASTGenVisitor {
535531 )
536532 }
537533
534+ func generate( keyPathComponent node: KeyPathComponentSyntax , baseExpr: BridgedExpr ) -> BridgedExpr {
535+ switch node. component {
536+ case . property( let prop) :
537+ let dotLoc = self . generateSourceLoc ( node. period)
538+ if prop. declName. baseName. presence == . missing {
539+ return BridgedErrorExpr . create (
540+ self . ctx,
541+ loc: BridgedSourceRange ( start: dotLoc, end: dotLoc)
542+ ) . asExpr
543+ } else if prop. declName. baseName. keywordKind == . `self` {
544+ // TODO: Diagnose if there's arguments
545+ assert ( prop. declName. argumentNames == nil )
546+
547+ return BridgedDotSelfExpr . createParsed (
548+ self . ctx,
549+ subExpr: baseExpr,
550+ dotLoc: dotLoc,
551+ selfLoc: self . generateSourceLoc ( prop. declName)
552+ ) . asExpr
553+ } else {
554+ let declNameRef = self . generateDeclNameRef ( declReferenceExpr: prop. declName)
555+ return BridgedUnresolvedDotExpr . createParsed (
556+ self . ctx,
557+ base: baseExpr,
558+ dotLoc: dotLoc,
559+ name: declNameRef. name,
560+ nameLoc: declNameRef. loc
561+ ) . asExpr
562+ }
563+
564+ case . optional( let comp) :
565+ if comp. questionOrExclamationMark. rawText == " ! " {
566+ return BridgedForceValueExpr . createParsed (
567+ self . ctx,
568+ subExpr: baseExpr,
569+ exclaimLoc: self . generateSourceLoc ( comp. questionOrExclamationMark)
570+ ) . asExpr
571+ } else {
572+ return BridgedBindOptionalExpr . createParsed (
573+ self . ctx,
574+ subExpr: baseExpr,
575+ questionLoc: self . generateSourceLoc ( comp. questionOrExclamationMark)
576+ ) . asExpr
577+ }
578+
579+ case . subscript( let comp) :
580+ return BridgedSubscriptExpr . createParsed (
581+ self . ctx,
582+ baseExpr: baseExpr,
583+ args: self . generateArgumentList (
584+ leftParen: comp. leftSquare,
585+ labeledExprList: comp. arguments,
586+ rightParen: comp. rightSquare,
587+ trailingClosure: nil ,
588+ additionalTrailingClosures: nil
589+ )
590+ ) . asExpr
591+ }
592+ }
593+
594+ func generate( keyPathExpr node: KeyPathExprSyntax ) -> BridgedExpr {
595+ guard !node. components. isEmpty else {
596+ // FIXME: Diagnostics KeyPath expression without any component.
597+ return BridgedErrorExpr . create ( self . ctx, loc: self . generateSourceRange ( node) ) . asExpr
598+ }
599+
600+ var rootExpr : BridgedExpr ?
601+ if let parsedType = node. root, !parsedType. is ( MissingTypeSyntax . self) {
602+ let rootType = self . generate ( type: parsedType)
603+ rootExpr = BridgedTypeExpr . createParsed ( self . ctx, type: rootType) . asExpr
604+ } else {
605+ rootExpr = nil
606+ }
607+
608+ var inRoot = rootExpr != nil
609+ var pathExpr : BridgedExpr ? = nil
610+
611+ for component in node. components {
612+ if inRoot {
613+ switch component. component {
614+ case // "root" expression is separated by '.?' or '.[idx]'
615+ . optional( _) where component. period != nil ,
616+ . subscript( _) where component. period != nil :
617+ inRoot = false
618+ default :
619+ rootExpr = self . generate ( keyPathComponent: component, baseExpr: rootExpr!)
620+ continue
621+ }
622+ }
623+
624+ if pathExpr == nil {
625+ // 'KeyPathDotExpr' is a dummy base expression.
626+ pathExpr = BridgedKeyPathDotExpr . createParsed (
627+ self . ctx,
628+ // Use 'component' instead of 'component.period' because period can
629+ // be nil (e.g. '\?'), but 'loc' must be a valid location.
630+ loc: self . generateSourceLoc ( component)
631+ ) . asExpr
632+ }
633+
634+ pathExpr = self . generate ( keyPathComponent: component, baseExpr: pathExpr!)
635+ }
636+
637+ return BridgedKeyPathExpr . createParsed (
638+ self . ctx,
639+ backslashLoc: self . generateSourceLoc ( node. backslash) ,
640+ parsedRoot: rootExpr. asNullable,
641+ parsedPath: pathExpr. asNullable,
642+ hasLeadingDot: rootExpr == nil
643+ ) . asExpr
644+ }
645+
538646 struct FreestandingMacroExpansionInfo {
539647 var poundLoc : BridgedSourceLoc
540648 var macroNameRef : BridgedDeclNameRef
0 commit comments