at main 2.2 kB view raw
1// SPDX-FileCopyrightText: 2025 The Project Pterodactyl Developers 2// 3// SPDX-License-Identifier: MPL-2.0 4 5import Foundation 6import LanguageServerProtocol 7 8extension SemanticTokenTypes { 9 public var index: Int { 10 Self.allCases.firstIndex(of: self)! 11 } 12} 13 14extension SemanticTokenModifiers { 15 private static let modifierBitPositions: [SemanticTokenModifiers: Int] = { 16 var dict: [SemanticTokenModifiers: Int] = [:] 17 for (i, modifier) in SemanticTokenModifiers.allCases.enumerated() { 18 dict[modifier] = i 19 } 20 return dict 21 }() 22 23 static func encodeBitset(_ modifiers: Set<SemanticTokenModifiers>) -> UInt32 { 24 var bitset: UInt32 = 0 25 for modifier in modifiers { 26 if let bit = modifierBitPositions[modifier] { 27 bitset |= (1 << bit) 28 } 29 } 30 return bitset 31 } 32} 33 34 35struct SingleLineRange { 36 let line: Int 37 let char: Int 38 let length: Int 39} 40 41 42extension TokenMetadata { 43 func semanticToken(range: SingleLineRange) -> SemanticToken? { 44 guard range.length > 0 else { return nil } 45 return SemanticToken( 46 line: UInt32(range.line), 47 char: UInt32(range.char), 48 length: UInt32(range.length), 49 type: UInt32(semanticTokenType.index), 50 modifiers: SemanticTokenModifiers.encodeBitset(semanticTokenModifiers) 51 ) 52 } 53} 54 55extension SyntaxCursor { 56 var singleLineRanges: [SingleLineRange] { 57 var result: [SingleLineRange] = [] 58 var location = lineMap.location(at: utf16Offset) 59 60 for line in node.text.split(omittingEmptySubsequences: false, whereSeparator: \.isNewline) { 61 let length = line.utf16.count 62 result.append(SingleLineRange(line: location.line, char: location.column, length: length)) 63 location.line += 1 64 location.column = 0 65 } 66 67 return result 68 } 69} 70 71extension SyntaxCursor { 72 public func collectSemanticTokens(_ sink: inout [SemanticToken]) { 73 if let (_, metadata) = node.token, let metadata { 74 for lineRange in singleLineRanges { 75 if let semanticToken = metadata.semanticToken(range: lineRange) { 76 sink.append(semanticToken) 77 } 78 } 79 } 80 81 for child in children { 82 child.collectSemanticTokens(&sink) 83 } 84 } 85 86 public var semanticTokens: [SemanticToken] { 87 var tokens: [SemanticToken] = [] 88 collectSemanticTokens(&tokens) 89 return tokens 90 } 91}