1010//
1111//===----------------------------------------------------------------------===//
1212import SwiftDiagnostics
13- import SwiftOperators
1413import SwiftSyntax
1514
1615/// Evaluate the condition of an `#if`.
@@ -29,7 +28,7 @@ import SwiftSyntax
2928/// condition holds with the given build configuration. The second whether
3029/// the build condition is a "versioned" check that implies that we shouldn't
3130/// diagnose syntax errors in blocks where the check fails.
32- private func evaluateIfConfig(
31+ func evaluateIfConfig(
3332 condition: ExprSyntax ,
3433 configuration: some BuildConfiguration ,
3534 diagnosticHandler: ( ( Diagnostic ) -> Void ) ?
@@ -406,162 +405,6 @@ private func evaluateIfConfig(
406405 throw recordedError ( . unknownExpression( condition) )
407406}
408407
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-
565408extension IfConfigClauseSyntax {
566409 /// Determine whether this condition is "versioned".
567410 func isVersioned(
0 commit comments