10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
13
+ import SwiftIfConfig
13
14
import SwiftSyntax
14
15
15
16
@_spi ( Experimental) extension SyntaxProtocol {
@@ -391,7 +392,11 @@ import SwiftSyntax
391
392
}
392
393
@_spi ( Experimental) extension ExtensionDeclSyntax : LookInMembersScopeSyntax {
393
394
@_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
395
400
}
396
401
397
402
@_spi ( Experimental) public var defaultIntroducedNames : [ LookupName ] {
@@ -420,8 +425,8 @@ import SwiftSyntax
420
425
+ defaultLookupImplementation( identifier, at: lookUpPosition, with: config, propagateToParent: false )
421
426
+ [ . lookInMembers( self ) ]
422
427
+ 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) {
425
430
return [ . lookInGenericParametersOfExtendedType( self ) ] + [ . lookInMembers( self ) ]
426
431
+ defaultLookupImplementation( identifier, at: lookUpPosition, with: config)
427
432
}
@@ -433,23 +438,6 @@ import SwiftSyntax
433
438
return [ . lookInGenericParametersOfExtendedType( self ) ]
434
439
+ lookupInParent( identifier, at: lookUpPosition, with: config)
435
440
}
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
- }
453
441
}
454
442
455
443
@_spi ( Experimental) extension AccessorDeclSyntax : ScopeSyntax {
@@ -491,7 +479,7 @@ import SwiftSyntax
491
479
492
480
let implicitSelf : [ LookupName ] = [ . implicit( . self ( self ) ) ]
493
481
. filter { name in
494
- checkIdentifier ( identifier, refersTo: name, at: lookUpPosition)
482
+ checkIdentifier ( identifier, refersTo: name, at: lookUpPosition) && !attributes . range . contains ( lookUpPosition )
495
483
}
496
484
497
485
return defaultLookupImplementation (
@@ -510,15 +498,40 @@ import SwiftSyntax
510
498
}
511
499
512
500
@_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
+ /// ```
514
521
@_spi ( Experimental) public var defaultIntroducedNames : [ LookupName ] {
522
+ var containsExpressionSyntax = false
523
+
515
524
let extractedNames = catchItems. flatMap { item in
516
525
guard let pattern = item. pattern else { return [ LookupName] ( ) }
517
526
527
+ if !containsExpressionSyntax && pattern. is ( ExpressionPatternSyntax . self) {
528
+ containsExpressionSyntax = true
529
+ }
530
+
518
531
return LookupName . getNames ( from: pattern)
519
532
}
520
533
521
- return extractedNames. isEmpty ? [ . implicit( . error( self ) ) ] : extractedNames
534
+ return extractedNames. isEmpty && !containsExpressionSyntax ? [ . implicit( . error( self ) ) ] : extractedNames
522
535
}
523
536
524
537
@_spi ( Experimental) public var scopeDebugName : String {
@@ -594,14 +607,27 @@ import SwiftSyntax
594
607
checkIdentifier ( identifier, refersTo: name, at: lookUpPosition)
595
608
}
596
609
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
+ }
605
631
}
606
632
}
607
633
@@ -697,6 +723,18 @@ import SwiftSyntax
697
723
}
698
724
}
699
725
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
+
700
738
@_spi ( Experimental)
701
739
extension SubscriptDeclSyntax : WithGenericParametersScopeSyntax , CanInterleaveResultsLaterScopeSyntax {
702
740
/// Parameters introduced by this subscript and possibly `self` keyword.
@@ -758,7 +796,7 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
758
796
) -> [ LookupResult ] {
759
797
var thisScopeResults : [ LookupResult ] = [ ]
760
798
761
- if !parameterClause . range. contains ( lookUpPosition) && !returnClause . range . contains ( lookUpPosition ) {
799
+ if accessorBlock ? . range. contains ( lookUpPosition) ?? false {
762
800
thisScopeResults = defaultLookupImplementation (
763
801
identifier,
764
802
at: position,
@@ -866,8 +904,6 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
866
904
with config: LookupConfig
867
905
) -> [ LookupResult ] {
868
906
if bindings. first? . accessorBlock? . range. contains ( lookUpPosition) ?? false {
869
- let isMember = parentScope? . is ( MemberBlockSyntax . self) ?? false
870
-
871
907
return defaultLookupImplementation (
872
908
in: ( isMember ? [ . implicit( . self ( self ) ) ] : LookupName . getNames ( from: self ) ) ,
873
909
identifier,
@@ -887,10 +923,99 @@ extension SubscriptDeclSyntax: WithGenericParametersScopeSyntax, CanInterleaveRe
887
923
with config: LookupConfig ,
888
924
resultsToInterleave: [ LookupResult ]
889
925
) -> [ LookupResult ] {
890
- guard parentScope ? . is ( MemberBlockSyntax . self ) ?? false else {
926
+ guard isMember else {
891
927
return lookup ( identifier, at: lookUpPosition, with: config)
892
928
}
893
929
894
930
return resultsToInterleave + lookupInParent( identifier, at: lookUpPosition, with: config)
895
931
}
896
932
}
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