// SPDX-FileCopyrightText: 2025 The Project Pterodactyl Developers // // SPDX-License-Identifier: MPL-2.0 import Foundation import LanguageServerProtocol extension SemanticTokenTypes { public var index: Int { Self.allCases.firstIndex(of: self)! } } extension SemanticTokenModifiers { private static let modifierBitPositions: [SemanticTokenModifiers: Int] = { var dict: [SemanticTokenModifiers: Int] = [:] for (i, modifier) in SemanticTokenModifiers.allCases.enumerated() { dict[modifier] = i } return dict }() static func encodeBitset(_ modifiers: Set) -> UInt32 { var bitset: UInt32 = 0 for modifier in modifiers { if let bit = modifierBitPositions[modifier] { bitset |= (1 << bit) } } return bitset } } struct SingleLineRange { let line: Int let char: Int let length: Int } extension TokenMetadata { func semanticToken(range: SingleLineRange) -> SemanticToken? { guard range.length > 0 else { return nil } return SemanticToken( line: UInt32(range.line), char: UInt32(range.char), length: UInt32(range.length), type: UInt32(semanticTokenType.index), modifiers: SemanticTokenModifiers.encodeBitset(semanticTokenModifiers) ) } } extension SyntaxCursor { var singleLineRanges: [SingleLineRange] { var result: [SingleLineRange] = [] var location = lineMap.location(at: utf16Offset) for line in node.text.split(omittingEmptySubsequences: false, whereSeparator: \.isNewline) { let length = line.utf16.count result.append(SingleLineRange(line: location.line, char: location.column, length: length)) location.line += 1 location.column = 0 } return result } } extension SyntaxCursor { public func collectSemanticTokens(_ sink: inout [SemanticToken]) { if let (_, metadata) = node.token, let metadata { for lineRange in singleLineRanges { if let semanticToken = metadata.semanticToken(range: lineRange) { sink.append(semanticToken) } } } for child in children { child.collectSemanticTokens(&sink) } } public var semanticTokens: [SemanticToken] { var tokens: [SemanticToken] = [] collectSemanticTokens(&tokens) return tokens } }