1010//
1111//===----------------------------------------------------------------------===//
1212
13+ import SwiftIfConfig
1314import SwiftSyntax
1415
1516@_spi ( Experimental) extension SyntaxProtocol {
@@ -391,7 +392,11 @@ import SwiftSyntax
391392}
392393@_spi ( Experimental) extension ExtensionDeclSyntax : LookInMembersScopeSyntax {
393394 @_spi ( Experimental) public var lookupMembersPosition : AbsolutePosition {
394- extendedType. position
395+ if let memberType = extendedType. as ( MemberTypeSyntax . self) {
396+ return memberType. name. positionAfterSkippingLeadingTrivia
397+ }
398+
399+ return extendedType. positionAfterSkippingLeadingTrivia
395400 }
396401
397402 @_spi ( Experimental) public var defaultIntroducedNames : [ LookupName ] {
@@ -420,8 +425,8 @@ import SwiftSyntax
420425 + defaultLookupImplementation( identifier, at: lookUpPosition, with: config, propagateToParent: false )
421426 + [ . lookInMembers( self ) ]
422427 + lookupInParent( identifier, at: lookUpPosition, with: config)
423- } else if !extendedType. range. contains ( lookUpPosition) && genericWhereClause != nil {
424- if inRightTypeOrSameTypeRequirement ( lookUpPosition) {
428+ } else if !extendedType. range. contains ( lookUpPosition) , let genericWhereClause {
429+ if genericWhereClause . range . contains ( lookUpPosition) {
425430 return [ . lookInGenericParametersOfExtendedType( self ) ] + [ . lookInMembers( self ) ]
426431 + defaultLookupImplementation( identifier, at: lookUpPosition, with: config)
427432 }
@@ -433,23 +438,6 @@ import SwiftSyntax
433438 return [ . lookInGenericParametersOfExtendedType( self ) ]
434439 + lookupInParent( identifier, at: lookUpPosition, with: config)
435440 }
436-
437- /// Returns `true` if `checkedPosition` is a right type of a
438- /// conformance requirement or inside a same type requirement.
439- private func inRightTypeOrSameTypeRequirement(
440- _ checkedPosition: AbsolutePosition
441- ) -> Bool {
442- genericWhereClause? . requirements. contains { elem in
443- switch Syntax ( elem. requirement) . as ( SyntaxEnum . self) {
444- case . conformanceRequirement( let conformanceRequirement) :
445- return conformanceRequirement. rightType. range. contains ( checkedPosition)
446- case . sameTypeRequirement( let sameTypeRequirement) :
447- return sameTypeRequirement. range. contains ( checkedPosition)
448- default :
449- return false
450- }
451- } ?? false
452- }
453441}
454442
455443@_spi ( Experimental) extension AccessorDeclSyntax : ScopeSyntax {
@@ -491,7 +479,7 @@ import SwiftSyntax
491479
492480 let implicitSelf : [ LookupName ] = [ . implicit( . self ( self ) ) ]
493481 . filter { name in
494- checkIdentifier ( identifier, refersTo: name, at: lookUpPosition)
482+ checkIdentifier ( identifier, refersTo: name, at: lookUpPosition) && !attributes . range . contains ( lookUpPosition )
495483 }
496484
497485 return defaultLookupImplementation (
@@ -510,15 +498,40 @@ import SwiftSyntax
510498}
511499
512500@_spi ( Experimental) extension CatchClauseSyntax : ScopeSyntax {
513- /// Implicit `error` when there are no catch items.
501+ /// Name introduced by the catch clause.
502+ ///
503+ /// `defaultIntroducedNames` contains implicit `error` name if
504+ /// no names are declared in catch items and they don't contain any expression patterns.
505+ /// Otherwise, `defaultIntroducedNames` contains names introduced by the clause.
506+ ///
507+ /// ### Example
508+ /// ```swift
509+ /// do {
510+ /// // ...
511+ /// } catch SomeError, .x(let a) {
512+ /// // <-- lookup here, result: [a]
513+ /// } catch .x(let a) {
514+ /// // <-- lookup here, result: [a]
515+ /// } catch SomeError {
516+ /// // <-- lookup here, result: [empty]
517+ /// } catch {
518+ /// // <-- lookup here, result: implicit(error)
519+ /// }
520+ /// ```
514521 @_spi ( Experimental) public var defaultIntroducedNames : [ LookupName ] {
522+ var containsExpressionSyntax = false
523+
515524 let extractedNames = catchItems. flatMap { item in
516525 guard let pattern = item. pattern else { return [ LookupName] ( ) }
517526
527+ if !containsExpressionSyntax && pattern. is ( ExpressionPatternSyntax . self) {
528+ containsExpressionSyntax = true
529+ }
530+
518531 return LookupName . getNames ( from: pattern)
519532 }
520533
521- return extractedNames. isEmpty ? [ . implicit( . error( self ) ) ] : extractedNames
534+ return extractedNames. isEmpty && !containsExpressionSyntax ? [ . implicit( . error( self ) ) ] : extractedNames
522535 }
523536
524537 @_spi ( Experimental) public var scopeDebugName : String {
@@ -594,14 +607,27 @@ import SwiftSyntax
594607 checkIdentifier ( identifier, refersTo: name, at: lookUpPosition)
595608 }
596609
597- return sequentialLookup (
598- in: statements,
599- identifier,
600- at: lookUpPosition,
601- with: config,
602- propagateToParent: false
603- ) + LookupResult. getResultArray ( for: self , withNames: filteredNamesFromLabel)
604- + ( config. finishInSequentialScope ? [ ] : lookupInParent ( identifier, at: lookUpPosition, with: config) )
610+ if label. range. contains ( lookUpPosition) {
611+ return config. finishInSequentialScope ? [ ] : lookupInParent ( identifier, at: lookUpPosition, with: config)
612+ } else if config. finishInSequentialScope {
613+ return sequentialLookup (
614+ in: statements,
615+ identifier,
616+ at: lookUpPosition,
617+ with: config,
618+ propagateToParent: false
619+ )
620+ } else {
621+ return sequentialLookup (
622+ in: statements,
623+ identifier,
624+ at: lookUpPosition,
625+ with: config,
626+ propagateToParent: false
627+ )
628+ + LookupResult. getResultArray ( for: self , withNames: filteredNamesFromLabel)
629+ + lookupInParent( identifier, at: lookUpPosition, with: config)
630+ }
605631 }
606632}
607633
@@ -697,6 +723,18 @@ import SwiftSyntax
697723 }
698724}
699725
726+ @_spi ( Experimental) extension MacroDeclSyntax : WithGenericParametersScopeSyntax {
727+ public var defaultIntroducedNames : [ LookupName ] {
728+ signature. parameterClause. parameters. flatMap { parameter in
729+ LookupName . getNames ( from: parameter)
730+ }
731+ }
732+
733+ @_spi ( Experimental) public var scopeDebugName : String {
734+ " MacroDeclScope "
735+ }
736+ }
737+
700738@_spi ( Experimental)
701739extension SubscriptDeclSyntax : WithGenericParametersScopeSyntax , CanInterleaveResultsLaterScopeSyntax {
702740 /// Parameters introduced by this subscript and possibly `self` keyword.
@@ -758,7 +796,7 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
758796 ) -> [ LookupResult ] {
759797 var thisScopeResults : [ LookupResult ] = [ ]
760798
761- if !parameterClause . range. contains ( lookUpPosition) && !returnClause . range . contains ( lookUpPosition ) {
799+ if accessorBlock ? . range. contains ( lookUpPosition) ?? false {
762800 thisScopeResults = defaultLookupImplementation (
763801 identifier,
764802 at: position,
@@ -866,8 +904,6 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
866904 with config: LookupConfig
867905 ) -> [ LookupResult ] {
868906 if bindings. first? . accessorBlock? . range. contains ( lookUpPosition) ?? false {
869- let isMember = parentScope? . is ( MemberBlockSyntax . self) ?? false
870-
871907 return defaultLookupImplementation (
872908 in: ( isMember ? [ . implicit( . self ( self ) ) ] : LookupName . getNames ( from: self ) ) ,
873909 identifier,
@@ -887,10 +923,99 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
887923 with config: LookupConfig ,
888924 resultsToInterleave: [ LookupResult ]
889925 ) -> [ LookupResult ] {
890- guard parentScope ? . is ( MemberBlockSyntax . self ) ?? false else {
926+ guard isMember else {
891927 return lookup ( identifier, at: lookUpPosition, with: config)
892928 }
893929
894930 return resultsToInterleave + lookupInParent( identifier, at: lookUpPosition, with: config)
895931 }
896932}
933+
934+ @_spi ( Experimental) extension DeinitializerDeclSyntax : ScopeSyntax {
935+ @_spi ( Experimental) public var defaultIntroducedNames : [ LookupName ] {
936+ [ . implicit( . self ( self ) ) ]
937+ }
938+
939+ @_spi ( Experimental) public var scopeDebugName : String {
940+ " DeinitializerScope "
941+ }
942+ }
943+
944+ @_spi ( Experimental) extension IfConfigDeclSyntax : IntroducingToSequentialParentScopeSyntax , SequentialScopeSyntax {
945+ /// Names from all clauses.
946+ var namesIntroducedToSequentialParent : [ LookupName ] {
947+ clauses. flatMap { clause in
948+ clause. elements. flatMap { element in
949+ LookupName . getNames ( from: element, accessibleAfter: element. endPosition)
950+ } ?? [ ]
951+ }
952+ }
953+
954+ /// Performs sequential lookup in the active clause.
955+ /// Active clause is determined by the `BuildConfiguration`
956+ /// inside `config`. If not specified, defaults to the `#else` clause.
957+ func lookupFromSequentialParent(
958+ _ identifier: Identifier ? ,
959+ at lookUpPosition: AbsolutePosition ,
960+ with config: LookupConfig
961+ ) -> [ LookupResult ] {
962+ let clause : IfConfigClauseSyntax ?
963+
964+ if let configuredRegions = config. configuredRegions {
965+ clause = configuredRegions. activeClause ( for: self )
966+ } else {
967+ clause =
968+ clauses
969+ . first { clause in
970+ clause. poundKeyword. tokenKind == . poundElse
971+ }
972+ }
973+
974+ return sequentialLookup (
975+ in: clause? . elements? . as ( CodeBlockItemListSyntax . self) ?? [ ] ,
976+ identifier,
977+ at: lookUpPosition,
978+ with: config,
979+ ignoreNamedDecl: true ,
980+ propagateToParent: false
981+ )
982+ }
983+
984+ /// Returns all `NamedDeclSyntax` nodes in the active clause specified
985+ /// by `BuildConfiguration` in `config` from bottom-most to top-most.
986+ func getNamedDecls( for config: LookupConfig ) -> [ NamedDeclSyntax ] {
987+ let clause : IfConfigClauseSyntax ?
988+
989+ if let configuredRegions = config. configuredRegions {
990+ clause = configuredRegions. activeClause ( for: self )
991+ } else {
992+ clause =
993+ clauses
994+ . first { clause in
995+ clause. poundKeyword. tokenKind == . poundElse
996+ }
997+ }
998+
999+ guard let clauseElements = clause? . elements? . as ( CodeBlockItemListSyntax . self) else { return [ ] }
1000+
1001+ var result : [ NamedDeclSyntax ] = [ ]
1002+
1003+ for elem in clauseElements. reversed ( ) {
1004+ if let namedDecl = elem. item. asProtocol ( NamedDeclSyntax . self) {
1005+ result. append ( namedDecl)
1006+ } else if let ifConfigDecl = elem. item. as ( IfConfigDeclSyntax . self) {
1007+ result += ifConfigDecl. getNamedDecls ( for: config)
1008+ }
1009+ }
1010+
1011+ return result
1012+ }
1013+
1014+ @_spi ( Experimental) public var defaultIntroducedNames : [ LookupName ] {
1015+ [ ]
1016+ }
1017+
1018+ @_spi ( Experimental) public var scopeDebugName : String {
1019+ " IfConfigScope "
1020+ }
1021+ }
0 commit comments