Files
SwiftLint/Tests/FrameworkTests/SwiftSyntaxKindBridgeTests.swift
Danny Mösch ac2eda6732 Adopt Swift Testing
# Conflicts:
#	Tests/BuiltInRulesTests/FileHeaderRuleTests.swift
#	Tests/BuiltInRulesTests/FileNameNoSpaceRuleTests.swift
#	Tests/BuiltInRulesTests/IndentationWidthRuleTests.swift
#	Tests/CoreTests/RegexConfigurationTests.swift
#	Tests/CoreTests/SwiftLintFileTests.swift
#	Tests/FileSystemAccessTests/BaselineTests.swift
#	Tests/FileSystemAccessTests/ConfigurationTests+Mock.swift
#	Tests/FileSystemAccessTests/ConfigurationTests.swift
#	Tests/FileSystemAccessTests/GlobTests.swift
#	Tests/FileSystemAccessTests/MultipleConfigurationsTests.swift
#	Tests/FileSystemAccessTests/ReporterTests.swift
#	Tests/FileSystemAccessTests/SourceKitCrashTests.swift
#	Tests/FrameworkTests/CustomRulesTests.swift
#	Tests/FrameworkTests/LinterCacheTests.swift
#	Tests/FrameworkTests/RuleConfigurationTests.swift
#	Tests/FrameworkTests/SwiftVersionTests.swift
#	Tests/GeneratedTests/GeneratedTests_02.swift
#	Tests/GeneratedTests/GeneratedTests_03.swift
#	Tests/GeneratedTests/GeneratedTests_04.swift
#	Tests/GeneratedTests/GeneratedTests_05.swift
#	Tests/GeneratedTests/GeneratedTests_06.swift
#	Tests/GeneratedTests/GeneratedTests_07.swift
#	Tests/GeneratedTests/GeneratedTests_08.swift
#	Tests/GeneratedTests/GeneratedTests_09.swift
#	Tests/GeneratedTests/GeneratedTests_10.swift
#	Tests/IntegrationTests/ConfigPathResolutionTests.swift
#	Tests/IntegrationTests/IntegrationTests.swift
#	Tests/TestHelpers/TestHelpers.swift
2026-06-06 11:07:04 +02:00

185 lines
7.0 KiB
Swift

import SourceKittenFramework
import SwiftIDEUtils
import Testing
@testable import SwiftLintCore
@Suite
struct SwiftSyntaxKindBridgeTests {
@Test
func basicKeywordMapping() {
// Test basic keyword mappings
#expect(SwiftSyntaxKindBridge.mapClassification(.keyword) == .keyword)
}
@Test
func identifierMapping() {
// Test identifier mappings
#expect(SwiftSyntaxKindBridge.mapClassification(.identifier) == .identifier)
#expect(SwiftSyntaxKindBridge.mapClassification(.dollarIdentifier) == .identifier)
}
@Test
func commentMapping() {
// Test comment mappings
#expect(SwiftSyntaxKindBridge.mapClassification(.lineComment) == .comment)
#expect(SwiftSyntaxKindBridge.mapClassification(.blockComment) == .comment)
#expect(SwiftSyntaxKindBridge.mapClassification(.docLineComment) == .docComment)
#expect(SwiftSyntaxKindBridge.mapClassification(.docBlockComment) == .docComment)
}
@Test
func literalMapping() {
// Test literal mappings
#expect(SwiftSyntaxKindBridge.mapClassification(.stringLiteral) == .string)
#expect(SwiftSyntaxKindBridge.mapClassification(.integerLiteral) == .number)
#expect(SwiftSyntaxKindBridge.mapClassification(.floatLiteral) == .number)
}
@Test
func operatorAndTypeMapping() {
// Test operator and type mappings
#expect(SwiftSyntaxKindBridge.mapClassification(.operator) == .operator)
#expect(SwiftSyntaxKindBridge.mapClassification(.type) == .typeidentifier)
}
@Test
func specialCaseMapping() {
// Test special case mappings
#expect(SwiftSyntaxKindBridge.mapClassification(.attribute) == .attributeID)
#expect(SwiftSyntaxKindBridge.mapClassification(.editorPlaceholder) == .placeholder)
#expect(SwiftSyntaxKindBridge.mapClassification(.ifConfigDirective) == .poundDirectiveKeyword)
#expect(SwiftSyntaxKindBridge.mapClassification(.argumentLabel) == .argument)
}
@Test
func unmappedClassifications() {
// Test classifications that have no mapping
#expect(SwiftSyntaxKindBridge.mapClassification(.none) == nil)
#expect(SwiftSyntaxKindBridge.mapClassification(.regexLiteral) == nil)
}
@Test
func sourceKittenSyntaxKindsGeneration() {
// Test that we can generate SourceKitten-compatible tokens from a simple Swift file
let contents = """
// This is a comment
let x = 42
"""
let file = SwiftLintFile(contents: contents)
// Get the tokens from the bridge
let tokens = SwiftSyntaxKindBridge.sourceKittenSyntaxKinds(for: file)
// Verify we got some tokens
#expect(!tokens.isEmpty)
// Check that we have expected token types
let tokenTypes = Set(tokens.map(\.value.type))
#expect(tokenTypes.contains(SyntaxKind.comment.rawValue))
#expect(tokenTypes.contains(SyntaxKind.keyword.rawValue))
#expect(tokenTypes.contains(SyntaxKind.identifier.rawValue))
#expect(tokenTypes.contains(SyntaxKind.number.rawValue))
}
@Test
func tokenOffsetAndLength() {
// Test that token offsets and lengths are correct
let contents = "let x = 42"
let file = SwiftLintFile(contents: contents)
let tokens = SwiftSyntaxKindBridge.sourceKittenSyntaxKinds(for: file)
// Find the "let" keyword token
let letToken = tokens.first { token in
if token.value.type == SyntaxKind.keyword.rawValue {
let start = token.value.offset.value
let end = token.value.offset.value + token.value.length.value
let startIndex = contents.index(contents.startIndex, offsetBy: start)
let endIndex = contents.index(contents.startIndex, offsetBy: end)
let substring = String(contents[startIndex..<endIndex])
return substring == "let"
}
return false
}
#expect(letToken != nil)
#expect(letToken?.value.offset.value == 0)
#expect(letToken?.value.length.value == 3)
// Find the number token
let numberToken = tokens.first { $0.value.type == SyntaxKind.number.rawValue }
#expect(numberToken != nil)
// "42" starts at offset 8 and has length 2
#expect(numberToken?.value.offset.value == 8)
#expect(numberToken?.value.length.value == 2)
}
@Test
func complexCodeStructure() {
// Test with more complex Swift code
let contents = """
import Foundation
/// A sample class
@objc
class MyClass {
// Properties
var name: String = "test"
let id = UUID()
func doSomething() {
print("Hello, \\(name)!")
}
}
"""
let file = SwiftLintFile(contents: contents)
let tokens = SwiftSyntaxKindBridge.sourceKittenSyntaxKinds(for: file)
// Verify we have various token types
let tokenTypes = Set(tokens.map(\.value.type))
#expect(tokenTypes.contains(SyntaxKind.keyword.rawValue)) // import, class, var, let, func
#expect(tokenTypes.contains(SyntaxKind.identifier.rawValue)) // Foundation, MyClass, name, etc.
#expect(tokenTypes.contains(SyntaxKind.docComment.rawValue)) // /// A sample class
#expect(tokenTypes.contains(SyntaxKind.comment.rawValue)) // // Properties
#expect(tokenTypes.contains(SyntaxKind.attributeID.rawValue)) // @objc // @objc
#expect(tokenTypes.contains(SyntaxKind.typeidentifier.rawValue)) // String, UUID
#expect(tokenTypes.contains(SyntaxKind.string.rawValue)) // "test", "Hello, \\(name)!"
}
@Test
func noSourceKitCallsAreMade() {
// This test verifies that the bridge doesn't make any SourceKit calls
// If it did, the validation system would fatal error in test mode
let contents = """
struct Test {
let value = 123
func method() -> Int { return value }
}
"""
let file = SwiftLintFile(contents: contents)
// This should succeed without any fatal errors from the validation system
let tokens = SwiftSyntaxKindBridge.sourceKittenSyntaxKinds(for: file)
#expect(!tokens.isEmpty)
}
@Test
func emptyFileHandling() {
// Test that empty files are handled gracefully
let file = SwiftLintFile(contents: "")
let tokens = SwiftSyntaxKindBridge.sourceKittenSyntaxKinds(for: file)
#expect(tokens.isEmpty)
}
@Test
func whitespaceOnlyFile() {
// Test files with only whitespace
let file = SwiftLintFile(contents: " \n\n \t \n")
let tokens = SwiftSyntaxKindBridge.sourceKittenSyntaxKinds(for: file)
// Whitespace is not classified, so we should get no tokens
#expect(tokens.isEmpty)
}
}