File: Assertions.swift

package info (click to toggle)
swiftlang 6.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 2,791,532 kB
  • sloc: cpp: 9,901,743; ansic: 2,201,431; asm: 1,091,827; python: 308,252; objc: 82,166; f90: 80,126; lisp: 38,358; pascal: 25,559; sh: 20,429; ml: 5,058; perl: 4,745; makefile: 4,484; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (122 lines) | stat: -rw-r--r-- 4,602 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

@_spi(Experimental) import SwiftLexicalLookup
import SwiftParser
@_spi(Testing) import SwiftSyntax
import XCTest
import _SwiftSyntaxTestSupport

/// `methodUnderTest` is called with the token at every position marker in the keys of `expected`.
/// It then asserts that the positions of the syntax nodes returned by `methodUnderTest` are the values in `expected`.
/// It also checks whether result types match rules specified in `expectedResultTypes`.
func assertLexicalScopeQuery(
  source: String,
  methodUnderTest: (_ marker: String, _ tokenAtMarker: TokenSyntax) -> ([SyntaxProtocol?]),
  expected: [String: [String?]],
  expectedResultTypes: MarkerExpectation = .none
) {
  // Extract markers
  let (markerDict, textWithoutMarkers) = extractMarkers(source)

  // Parse the test source
  var parser = Parser(textWithoutMarkers)
  let sourceFileSyntax = SourceFileSyntax.parse(from: &parser)

  // Iterate through the expected results
  for (marker, expectedMarkers) in expected {
    // Extract a test argument
    guard let position = markerDict[marker],
      let testArgument = sourceFileSyntax.token(at: AbsolutePosition(utf8Offset: position))
    else {
      XCTFail("Could not find token at location \(marker)")
      continue
    }

    // Execute the tested method
    let result = methodUnderTest(marker, testArgument)

    // Extract the expected results for the test argument
    let expectedPositions: [AbsolutePosition?] = expectedMarkers.map { expectedMarker in
      guard let expectedMarker else { return nil }

      guard let expectedPosition = markerDict[expectedMarker]
      else {
        XCTFail("Could not find position for \(marker)")
        return nil
      }

      return AbsolutePosition(utf8Offset: expectedPosition)
    }

    // Compare number of actual results to the number of expected results
    if result.count != expectedPositions.count {
      XCTFail(
        "For marker \(marker), actual number of elements: \(result.count) doesn't match the expected: \(expectedPositions.count)"
      )
    }

    // Assert validity of the output
    for (actual, (expectedMarker, expectedPosition)) in zip(result, zip(expectedMarkers, expectedPositions)) {
      guard let actual, let expectedPosition else { continue }
      XCTAssert(
        actual.positionAfterSkippingLeadingTrivia == expectedPosition,
        "For marker \(marker), actual result: \(actual) doesn't match expected value: \(sourceFileSyntax.token(at: expectedPosition)?.description ?? "nil")"
      )

      if let expectedMarker {
        expectedResultTypes.assertMarkerType(marker: expectedMarker, actual: actual)
      }
    }
  }
}

/// Name lookup is called with the token at every position marker in the keys of `expected`.
/// It then asserts that the positions of the syntax nodes returned by the lookup are the values in `expected`.
/// It also checks whether result types match rules specified in `expectedResultTypes`.
func assertLexicalNameLookup(
  source: String,
  references: [String: [ResultExpectation]],
  expectedResultTypes: MarkerExpectation = .none,
  useNilAsTheParameter: Bool = false,
  config: LookupConfig = LookupConfig()
) {
  assertLexicalScopeQuery(
    source: source,
    methodUnderTest: { marker, tokenAtMarker in
      let lookupIdentifier = Identifier(tokenAtMarker)

      let result = tokenAtMarker.lookup(useNilAsTheParameter ? nil : lookupIdentifier, with: config)

      guard let expectedValues = references[marker] else {
        XCTFail("For marker \(marker), couldn't find result expectation")
        return []
      }

      ResultExpectation.assertResult(marker: marker, result: result, expectedValues: expectedValues)

      return result.flatMap { lookUpResult in
        lookUpResult.names.map { lookupName in
          lookupName.syntax
        }
      }
    },
    expected: references.mapValues { expectations in
      expectations.flatMap { expectation in
        expectation.expectedNames.map { expectedName in
          expectedName.marker
        }
      }
    },
    expectedResultTypes: expectedResultTypes
  )
}