10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
import SwiftDiagnostics
13
- import SwiftOperators
14
13
import SwiftSyntax
15
14
16
15
/// Evaluate the condition of an `#if`.
@@ -29,7 +28,7 @@ import SwiftSyntax
29
28
/// condition holds with the given build configuration. The second whether
30
29
/// the build condition is a "versioned" check that implies that we shouldn't
31
30
/// diagnose syntax errors in blocks where the check fails.
32
- private func evaluateIfConfig(
31
+ func evaluateIfConfig(
33
32
condition: ExprSyntax ,
34
33
configuration: some BuildConfiguration ,
35
34
diagnosticHandler: ( ( Diagnostic ) -> Void ) ?
@@ -406,162 +405,6 @@ private func evaluateIfConfig(
406
405
throw recordedError ( . unknownExpression( condition) )
407
406
}
408
407
409
- extension ConfiguredRegionState {
410
- /// Evaluate the given `#if` condition using the given build configuration, throwing an error if there is
411
- /// insufficient information to make a determination.
412
- public init (
413
- condition: some ExprSyntaxProtocol ,
414
- configuration: some BuildConfiguration ,
415
- diagnosticHandler: ( ( Diagnostic ) -> Void ) ? = nil
416
- ) throws {
417
- // Apply operator folding for !/&&/||.
418
- let foldedCondition = try OperatorTable . logicalOperators. foldAll ( condition) { error in
419
- diagnosticHandler ? ( error. asDiagnostic)
420
- throw error
421
- } . cast ( ExprSyntax . self)
422
-
423
- let ( active, versioned) = try evaluateIfConfig (
424
- condition: foldedCondition,
425
- configuration: configuration,
426
- diagnosticHandler: diagnosticHandler
427
- )
428
-
429
- switch ( active, versioned) {
430
- case ( true , _) : self = . active
431
- case ( false , false ) : self = . inactive
432
- case ( false , true ) : self = . unparsed
433
- }
434
- }
435
- }
436
-
437
- extension IfConfigDeclSyntax {
438
- /// Given a particular build configuration, determine which clause (if any) is the "active" clause.
439
- ///
440
- /// For example, for code like the following:
441
- /// ```
442
- /// #if A
443
- /// func f()
444
- /// #elseif B
445
- /// func g()
446
- /// #endif
447
- /// ```
448
- ///
449
- /// If the `A` configuration option was passed on the command line (e.g. via `-DA`), the first clause
450
- /// (containing `func f()`) would be returned. If not, and if the `B`configuration was passed on the
451
- /// command line, the second clause (containing `func g()`) would be returned. If neither was
452
- /// passed, this function will return `nil` to indicate that none of the regions are active.
453
- ///
454
- /// If an error occurrs while processing any of the `#if` clauses,
455
- /// that clause will be considered inactive and this operation will
456
- /// continue to evaluate later clauses.
457
- public func activeClause(
458
- in configuration: some BuildConfiguration ,
459
- diagnosticHandler: ( ( Diagnostic ) -> Void ) ? = nil
460
- ) -> IfConfigClauseSyntax ? {
461
- for clause in clauses {
462
- // If there is no condition, we have reached an unconditional clause. Return it.
463
- guard let condition = clause. condition else {
464
- return clause
465
- }
466
-
467
- // If this condition evaluates true, return this clause.
468
- let isActive =
469
- ( try ? evaluateIfConfig (
470
- condition: condition,
471
- configuration: configuration,
472
- diagnosticHandler: diagnosticHandler
473
- ) ) ? . active ?? false
474
- if isActive {
475
- return clause
476
- }
477
- }
478
-
479
- return nil
480
- }
481
- }
482
-
483
- extension SyntaxProtocol {
484
- /// Determine whether the given syntax node is active within the given build configuration.
485
- ///
486
- /// This function evaluates the enclosing stack of `#if` conditions to determine whether the
487
- /// given node is active in the program when it is compiled with the given build configuration.
488
- ///
489
- /// For example, given code like the following:
490
- /// #if DEBUG
491
- /// #if A
492
- /// func f()
493
- /// #elseif B
494
- /// func g()
495
- /// #endif
496
- /// #endif
497
- ///
498
- /// a call to `isActive` on the syntax node for the function `g` would return `active` when the
499
- /// configuration options `DEBUG` and `B` are provided, but `A` is not.
500
- public func isActive(
501
- in configuration: some BuildConfiguration ,
502
- diagnosticHandler: ( ( Diagnostic ) -> Void ) ? = nil
503
- ) throws -> ConfiguredRegionState {
504
- var currentNode : Syntax = Syntax ( self )
505
- var currentState : ConfiguredRegionState = . active
506
-
507
- while let parent = currentNode. parent {
508
- // If the parent is an `#if` configuration, check whether our current
509
- // clause is active. If not, we're in an inactive region. We also
510
- // need to determine whether
511
- if let ifConfigClause = currentNode. as ( IfConfigClauseSyntax . self) ,
512
- let ifConfigDecl = ifConfigClause. parent? . parent? . as ( IfConfigDeclSyntax . self)
513
- {
514
- let activeClause = ifConfigDecl. activeClause (
515
- in: configuration,
516
- diagnosticHandler: diagnosticHandler
517
- )
518
-
519
- if activeClause != ifConfigClause {
520
- // This was not the active clause, so we know that we're in an
521
- // inactive block. However, if the condition is versioned, this is an
522
- // unparsed region.
523
- let isVersioned =
524
- ( try ? ifConfigClause. isVersioned (
525
- configuration: configuration,
526
- diagnosticHandler: diagnosticHandler
527
- ) ) ?? true
528
- if isVersioned {
529
- return . unparsed
530
- }
531
-
532
- currentState = . inactive
533
- }
534
- }
535
-
536
- currentNode = parent
537
- }
538
-
539
- return currentState
540
- }
541
-
542
- /// Determine whether the given syntax node is active given a set of
543
- /// configured regions as produced by `configuredRegions(in:)`.
544
- ///
545
- /// This is
546
- /// an approximation
547
- public func isActive(
548
- inConfiguredRegions regions: [ ( IfConfigClauseSyntax , ConfiguredRegionState ) ]
549
- ) -> ConfiguredRegionState {
550
- var currentState : ConfiguredRegionState = . active
551
- for (ifClause, state) in regions {
552
- if self . position < ifClause. position {
553
- return currentState
554
- }
555
-
556
- if self . position <= ifClause. endPosition {
557
- currentState = state
558
- }
559
- }
560
-
561
- return currentState
562
- }
563
- }
564
-
565
408
extension IfConfigClauseSyntax {
566
409
/// Determine whether this condition is "versioned".
567
410
func isVersioned(
0 commit comments