diff --git a/.github/workflows/build-and-test-template.yml b/.github/workflows/build-and-test-template.yml index 17cceda..60d6f38 100644 --- a/.github/workflows/build-and-test-template.yml +++ b/.github/workflows/build-and-test-template.yml @@ -135,10 +135,10 @@ jobs: - name: Generate LLVM pkgconfig file run: | set -eo pipefail - cd hylo swift package resolve .build/checkouts/Swifty-LLVM/Tools/make-pkgconfig.sh llvm.pc cat llvm.pc + working-directory: hylo - name: Build (${{ inputs.build-type }}) id: build @@ -166,49 +166,74 @@ jobs: ${{ env.BUILD_DIR }}/hylo-lsp-client ${{ env.BUILD_DIR }}/hylo-lsp-server - # build-native-windows: - # name: "Build and test: windows-latest/release" - # strategy: - # fail-fast: false - # runs-on: windows-latest - # steps: - # - name: Setup swift - # uses: compnerd/gha-setup-swift@main - # with: - # branch: swift-5.8.1-release - # tag: 5.8.1-RELEASE - - # - uses: actions/checkout@v3 - - # - name: Swift version - # run: swift --version - - # - name: Set up LLVM 15.0.6 - # run: | - # curl.exe -L -O -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"https://github.com/c3lang/win-llvm/releases/download/llvm_15_0_6/llvm-15.0.6-windows-x86-msvc17-msvcrt.7z - # 7z x llvm-15.0.6-windows-x86-msvc17-msvcrt.7z -oC:\ - # Add-Content $env:GITHUB_PATH 'C:\llvm-15.0.6-windows-x86-msvc17-msvcrt\bin' - - # - name: Copy LLVM's include and lib to include and lib folder of MSVC - # run: | - # xcopy c:\llvm-15.0.6-windows-x86-msvc17-msvcrt\include\*.* c:\program" "files\microsoft" "visual" "studio\2022\enterprise\vc\tools\msvc\${{ env.VCToolsVersion }}\include\ /s /h - # xcopy c:\llvm-15.0.6-windows-x86-msvc17-msvcrt\lib\*.* c:\program" "files\microsoft" "visual" "studio\2022\enterprise\vc\tools\msvc\${{ env.VCToolsVersion }}\lib\x64\ /s /h - - # - run: llvm-config --version - - # - name: Build support library - # run: clang -c ./Library/Hylo/LibC.c -o HyloLibC.lib - - # - name: Copy support library - # run: xcopy HyloLibC.lib c:\program" "files\microsoft" "visual" "studio\2022\enterprise\vc\tools\msvc\${{ env.VCToolsVersion }}\lib\x64\ - - # - name: Build (Release) - # id: build - # continue-on-error: true - # run: swift build -v -c release - - # - name: Retry on failure - # continue-on-error: false - # if: steps.build.outcome != 'success' - # run: swift build -v -c release + build-native-windows: + name: "Build and test: windows-latest/${{ inputs.build-type }}" + # strategy: + # fail-fast: false + runs-on: windows-latest + steps: + - name: Setup swift + uses: compnerd/gha-setup-swift@main + with: + branch: swift-5.9-release + tag: 5.9-RELEASE + + - uses: actions/checkout@v3 + with: + submodules: 'true' + + - name: Swift version + run: swift --version + + - name: Set up LLVM 15.0.6 + run: | + curl.exe -L -O -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"https://github.com/c3lang/win-llvm/releases/download/llvm_15_0_6/llvm-15.0.6-windows-x86-msvc17-msvcrt.7z + 7z x llvm-15.0.6-windows-x86-msvc17-msvcrt.7z -oC:\ + Add-Content $env:GITHUB_PATH 'C:\llvm-15.0.6-windows-x86-msvc17-msvcrt\bin' + working-directory: hylo + + - name: Copy LLVM's include and lib to include and lib folder of MSVC + run: | + xcopy c:\llvm-15.0.6-windows-x86-msvc17-msvcrt\include\*.* c:\program" "files\microsoft" "visual" "studio\2022\enterprise\vc\tools\msvc\${{ env.VCToolsVersion }}\include\ /s /h + xcopy c:\llvm-15.0.6-windows-x86-msvc17-msvcrt\lib\*.* c:\program" "files\microsoft" "visual" "studio\2022\enterprise\vc\tools\msvc\${{ env.VCToolsVersion }}\lib\x64\ /s /h + working-directory: hylo + + - run: llvm-config --version + + - name: Build support library + run: clang -c ./Library/Hylo/LibC.c -o HyloLibC.lib + working-directory: hylo + + - name: Copy support library + run: xcopy HyloLibC.lib c:\program" "files\microsoft" "visual" "studio\2022\enterprise\vc\tools\msvc\${{ env.VCToolsVersion }}\lib\x64\ + working-directory: hylo + + - name: Build (Release) + id: build + # continue-on-error: true + run: | + $BUILD_DIR = swift build -c ${{ inputs.build-type }} --show-bin-path + echo BUILD_DIR=$BUILD_DIR + echo BUILD_DIR=$BUILD_DIR >> $env:GITHUB_ENV + swift build -c ${{ inputs.build-type }} + + # - name: Copy artifacts + # run: | + # $BUILD_DIR = swift build -c ${{ inputs.build-type }} --show-bin-path + # xcopy $BUILD_DIR artifacts /I + + - name: Upload Hylo LSP artifacts (${{ inputs.build-type }}) + uses: actions/upload-artifact@v3 + with: + name: hylo-lsp-artifacts-windows + path: | + ${{ env.BUILD_DIR }}/hylo-lsp-client.exe + ${{ env.BUILD_DIR }}/hylo-lsp-server.exe + # artifacts/hylo-lsp-client.exe + # artifacts/hylo-lsp-server.exe + + # - name: Retry on failure + # continue-on-error: false + # if: steps.build.outcome != 'success' + # run: swift build -v -c release diff --git a/LanguageClient b/LanguageClient index 0614e3e..0543134 160000 --- a/LanguageClient +++ b/LanguageClient @@ -1 +1 @@ -Subproject commit 0614e3e373104c6df6cd24e02f6a08788021f30b +Subproject commit 05431343c5c0867398baadeb427610d3ab8fbf58 diff --git a/Package.swift b/Package.swift index a0d52bb..6fe180a 100644 --- a/Package.swift +++ b/Package.swift @@ -63,13 +63,30 @@ let package = Package( // dependencies: ["LanguageServerProtocol", "LanguageClient"], dependencies: [ "hylo-lsp", - "JSONRPC-DataChannel-UniSocket", + .product( + name: "JSONRPC-DataChannel-UniSocket", + package: "JSONRPC-DataChannel-UniSocket", + condition: .when(platforms: [ + .linux, + .macOS, + // .windows, + ]) + ), + + // "JSONRPC-DataChannel-UniSocket", // "JSONRPC-DataChannel-Actor", // "JSONRPC-DataChannel-StdioPipe", // .product(name: "ProcessEnv", package: "ProcessEnv", condition: .when(platforms: [.macOS])), ], // dependencies: ["LanguageServerProtocol", "UniSocket"], - path: "Sources/hylo-lsp-server" + path: "Sources/hylo-lsp-server", + swiftSettings: [ + .unsafeFlags(["-parse-as-library"], + .when(platforms: [ + .windows, + ]) + ) + ] ), .executableTarget( @@ -79,30 +96,32 @@ let package = Package( // .product(name: "ConsoleKit", package: "console-kit"), "hylo-lsp", "LanguageClient", - "JSONRPC-DataChannel-UniSocket", + .product( + name: "JSONRPC-DataChannel-UniSocket", + package: "JSONRPC-DataChannel-UniSocket", + condition: .when(platforms: [ + .linux, + .macOS, + // .windows, + ]) + ), + + // "JSONRPC-DataChannel-UniSocket", // "JSONRPC-DataChannel-Actor", // "JSONRPC-DataChannel-StdioPipe", ], // dependencies: ["LanguageServerProtocol", "UniSocket"], - path: "Sources/hylo-lsp-client" - ), - + path: "Sources/hylo-lsp-client", + swiftSettings: [ + .unsafeFlags(["-parse-as-library"], + .when(platforms: [ + .windows, + ]) + ) + ] - // .executableTarget( - // name: "hylo-lsp-client", - // // dependencies: ["LanguageServerProtocol", "LanguageClient"], - // dependencies: [ - // "LanguageServerProtocol", - // // "UniSocket", - // .product(name: "UniSocket", package: "swift-unisocket"), - // .product(name: "ProcessEnv", package: "ProcessEnv", condition: .when(platforms: [.macOS])), - // ], - // // dependencies: ["LanguageServerProtocol", "UniSocket"], - // path: "Client" - // ), + ), - // .target( - // name: "hylo-lsp"), .testTarget( name: "hylo-lspTests", dependencies: ["hylo-lsp-server"]), diff --git a/Sources/hylo-lsp-client/HyloClientTests.swift b/Sources/hylo-lsp-client/HyloClientTests.swift index b0c4700..9d8bbbd 100644 --- a/Sources/hylo-lsp-client/HyloClientTests.swift +++ b/Sources/hylo-lsp-client/HyloClientTests.swift @@ -5,8 +5,6 @@ import LanguageClient import LanguageServerProtocol import LanguageServerProtocol_Client import JSONRPC -import UniSocket -import JSONRPC_DataChannel_UniSocket import Core import FrontEnd diff --git a/Sources/hylo-lsp-client/hylo-lsp-client.swift b/Sources/hylo-lsp-client/hylo-lsp-client-cli.swift similarity index 90% rename from Sources/hylo-lsp-client/hylo-lsp-client.swift rename to Sources/hylo-lsp-client/hylo-lsp-client-cli.swift index d496dbd..e596802 100644 --- a/Sources/hylo-lsp-client/hylo-lsp-client.swift +++ b/Sources/hylo-lsp-client/hylo-lsp-client-cli.swift @@ -4,8 +4,8 @@ import LanguageClient import LanguageServerProtocol import LanguageServerProtocol_Client import JSONRPC -import UniSocket -import JSONRPC_DataChannel_UniSocket +// import UniSocket +// import JSONRPC_DataChannel_UniSocket // import JSONRPC_DataChannel_Actor import ArgumentParser import Logging @@ -15,6 +15,9 @@ import Core import FrontEnd import IR +#if !os(Windows) +import RegexBuilder +#endif // Allow loglevel as `ArgumentParser.Option` extension Logger.Level : ExpressibleByArgument { @@ -37,7 +40,32 @@ struct Options: ParsableArguments { public func parseDocument() throws -> (path: String, line: UInt?, char: UInt?) { - let search1 = #/(.+)(?::(\d+)(?:\.(\d+))?)/# + #if os(Windows) + // let search1 = try Regex(#"(.+)(?::(\d+)(?:\.(\d+))?)"#) + logger.warning("Document path parsing not currently supported on Windows, assuming normal filepath") + return (document, nil, nil) + #else + // NOTE: Can not use regex literal, it messes with the conditional windows compilation somehow... + // let search1 = #/(.+)(?::(\d+)(?:\.(\d+))?)/# + let search1 = Regex { + Capture { + OneOrMore(.any) + } + Regex { + ":" + Capture { + OneOrMore(.digit) + } + Optionally { + Regex { + "." + Capture { + OneOrMore(.digit) + } + } + } + } + } var path = document var line: UInt? @@ -60,7 +88,8 @@ struct Options: ParsableArguments { } } - return (String(path), line, char) + return (path, line, char) + #endif } func validate() throws { @@ -254,7 +283,7 @@ extension HyloLspCommand { // let docURL = URL.init(fileURLWithPath: options.document) let (doc, line, _) = try options.parseDocument() let docURL = URL.init(fileURLWithPath: doc) - let workspace = docURL.deletingLastPathComponent() + // let workspace = docURL.deletingLastPathComponent() if let pipe = options.pipe { print("starting client witn named pipe: \(pipe)") diff --git a/Sources/hylo-lsp-server/hylo-lsp-cli.swift b/Sources/hylo-lsp-server/hylo-lsp-server-cli.swift similarity index 79% rename from Sources/hylo-lsp-server/hylo-lsp-cli.swift rename to Sources/hylo-lsp-server/hylo-lsp-server-cli.swift index d779345..8ae5841 100644 --- a/Sources/hylo-lsp-server/hylo-lsp-cli.swift +++ b/Sources/hylo-lsp-server/hylo-lsp-server-cli.swift @@ -2,14 +2,18 @@ import Foundation // import ProcessEnv import LanguageServerProtocol import JSONRPC -import UniSocket -import JSONRPC_DataChannel_UniSocket // import JSONRPC_DataChannel_StdioPipe import ArgumentParser import hylo_lsp import Logging import Puppy +#if !os(Windows) +import UniSocket +import JSONRPC_DataChannel_UniSocket +#endif + + extension Bool { var intValue: Int { return self ? 1 : 0 @@ -54,6 +58,19 @@ struct HyloLspCommand: AsyncParsableCommand { await server.run() } + func puppyLevel(_ level: Logger.Level) -> LogLevel { + // LogLevel(rawValue: level.rawValue) + switch level { + case .trace: .trace + case .debug: .debug + case .info: .info + case .notice: .notice + case .warning: .warning + case .error: .error + case .critical: .critical + } + } + func run() async throws { // Force line buffering @@ -63,7 +80,7 @@ struct HyloLspCommand: AsyncParsableCommand { let logFileURL = URL(fileURLWithPath: logFile) // let fileLogger = try FileLogging(to: logFileURL) let fileLogger = try FileLogger("hylo-lsp", - logLevel: .info, + logLevel: puppyLevel(log), fileURL: logFileURL) var puppy = Puppy() puppy.add(fileLogger) @@ -85,6 +102,9 @@ struct HyloLspCommand: AsyncParsableCommand { // return handler // } + logger = Logger(label: loggerLabel) { label in + PuppyLogHandler(label: label, puppy: puppy) + } logger.logLevel = log await run(logger: logger, channel: DataChannel.stdioPipe()) @@ -96,13 +116,14 @@ struct HyloLspCommand: AsyncParsableCommand { logger = Logger(label: loggerLabel) { label in MultiplexLogHandler([ // FileLogHandler(label: label, fileLogger: fileLogger), - PuppyLogHandler(label: loggerLabel, puppy: puppy), - StreamLogHandler.standardOutput(label: loggerLabel) + PuppyLogHandler(label: label, puppy: puppy), + StreamLogHandler.standardOutput(label: label) ]) } logger.logLevel = log + #if !os(Windows) if let socket = socket { // throw ValidationError("TODO: socket transport: \(socket)") let socket = try UniSocket(type: .tcp, peer: socket, timeout: (connect: 5, read: nil, write: 5)) @@ -114,5 +135,13 @@ struct HyloLspCommand: AsyncParsableCommand { try socket.attach() await run(logger: logger, channel: DataChannel(socket: socket)) } + #else + if let _ = socket { + fatalError("socket mode not supported"); + } + else if let _ = pipe { + fatalError("pipe mode not supported"); + } + #endif } } diff --git a/Sources/hylo-lsp/AST+GetSemanticTokens.swift b/Sources/hylo-lsp/AST+GetSemanticTokens.swift index 0be9b36..2163502 100644 --- a/Sources/hylo-lsp/AST+GetSemanticTokens.swift +++ b/Sources/hylo-lsp/AST+GetSemanticTokens.swift @@ -69,7 +69,7 @@ struct SemanticTokensWalker { case let d as TraitDecl: addTrait(d) default: - print("Unknown node: \(node)") + logger.warning("Unknown node: \(node)") } } @@ -250,7 +250,7 @@ struct SemanticTokensWalker { let d = program.referredDecl[n] let t = tokenType(d) if d != nil && t == .unknown { - print("Unknown decl reference: \(d!)") + logger.warning("Unknown decl reference: \(d!)") } addToken(range: e.name.site, type: t) @@ -577,7 +577,7 @@ struct SemanticTokensWalker { case let s as DiscardStmt: addExpr(s.expr) default: - print("Unknown statement: \(s)") + logger.warning("Unknown statement: \(s)") } } diff --git a/Sources/hylo-lsp/AST+ListDocumentSymbols.swift b/Sources/hylo-lsp/AST+ListDocumentSymbols.swift index 4ab28f7..2ce8599 100644 --- a/Sources/hylo-lsp/AST+ListDocumentSymbols.swift +++ b/Sources/hylo-lsp/AST+ListDocumentSymbols.swift @@ -53,7 +53,7 @@ struct DocumentSymbolWalker { case let d as TraitDecl: addMembers(d.members) default: - // print("Ignored declaration node: \(node)") + // logger.warning("Ignored declaration node: \(node)") break } } diff --git a/Sources/hylo-lsp/HyloServer.swift b/Sources/hylo-lsp/HyloServer.swift index e2539e7..71b7482 100644 --- a/Sources/hylo-lsp/HyloServer.swift +++ b/Sources/hylo-lsp/HyloServer.swift @@ -20,6 +20,7 @@ public class LspState { // var program: TypedProgram? var documentProvider: DocumentProvider // var uri: DocumentUri? + var rootUri: String? public init(lsp: JSONRPCServer) { // self.ast = ast @@ -170,6 +171,7 @@ public struct HyloRequestHandler : RequestHandler { // let fm = FileManager.default if let rootUri = params.rootUri { + state.rootUri = rootUri // guard let path = URL(string: rootUri) else { // return .failure(JSONRPCResponseError(code: ErrorCodes.ServerNotInitialized, message: "invalid rootUri uri format")) // } @@ -328,7 +330,7 @@ public struct HyloRequestHandler : RequestHandler { // logger.debug("Function: \(f)") // } default: - logger.error("Unknown declaration kind: \(d!)") + logger.warning("Unknown declaration kind: \(d!)") break } @@ -396,7 +398,7 @@ public struct HyloRequestHandler : RequestHandler { case let u as TraitType: return u.name.value default: - logger.error("Unexpected type: \(t.base)") + logger.warning("Unexpected type: \(t.base)") return "unknown" } } @@ -523,14 +525,14 @@ public struct HyloRequestHandler : RequestHandler { let docResult = await state.documentProvider.getDocument(params.textDocument) switch docResult { - case let .success(doc): + case .success: return .success(RelatedDocumentDiagnosticReport(kind: .full, items: [])) case let .failure(error): switch error { case let .diagnostics(d): let dList = d.elements.map { LanguageServerProtocol.Diagnostic($0) } return .success(RelatedDocumentDiagnosticReport(kind: .full, items: dList)) - case let .other(e): + case .other: return .failure(JSONRPCResponseError(code: ErrorCodes.InternalError, message: "Unknown build error: \(error)")) } } @@ -560,7 +562,7 @@ public struct HyloRequestHandler : RequestHandler { case let .diagnostics(d): logger.warning("Program build failed\n\n\(d)") return .success(nil) - case let .other(e): + case .other: return .failure(JSONRPCResponseError(code: ErrorCodes.InternalError, message: "Unknown build error: \(error)")) } }