Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LSP (Python and Java Intellisense) #1104 #1128

Merged
merged 19 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ concurrency:
jobs:
deploy:
name: Deploying to TestFlight
runs-on: macOS-13
runs-on: macOS-14

steps:
- name: Checkout repository
Expand Down Expand Up @@ -39,7 +39,7 @@ jobs:
JUDGE0_KEY: ""
JUDGE0_ENDPOINT: ""
DISTRIBUTE_EXTERNAL: "true"
XCODE_PATH: "/Applications/Xcode_15.2.app"
XCODE_PATH: "/Applications/Xcode_15.4.app"

- name: Upload Artifact
uses: actions/upload-artifact@v3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ concurrency:
jobs:
deploy:
name: Deploying to App Store
runs-on: macOS-13
runs-on: macOS-14

steps:
- name: Checkout repository
Expand Down Expand Up @@ -37,4 +37,4 @@ jobs:
JUDGE0_KEY: "${{ secrets.JUDGE0_KEY }}"
JUDGE0_ENDPOINT: "${{ secrets.JUDGE0_ENDPOINT }}"
DISTRIBUTE_EXTERNAL: "false"
XCODE_PATH: "/Applications/Xcode_15.2.app"
XCODE_PATH: "/Applications/Xcode_15.4.app"
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

jobs:
Linting:
runs-on: macOS-13
runs-on: macOS-14
steps:
- uses: actions/checkout@v3
- name: Install swift-format
Expand All @@ -17,4 +17,4 @@ jobs:
- name: Unit Tests
run: fastlane tests
env:
XCODE_PATH: "/Applications/Xcode_15.2.app"
XCODE_PATH: "/Applications/Xcode_15.4.app"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Code.xcworkspace/xcuserdata/
Code.xcodeproj/xcuserdata/
Code.xcodeproj/project.xcworkspace/xcuserdata/
Code.ipa
Dependencies/monaco-textmate*/
LanguageResources/python-lsp/

Pods/

Expand Down
127 changes: 118 additions & 9 deletions Code.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,51 @@
"version": "0.5.1"
}
},
{
"package": "swift-atomics",
"repositoryURL": "https://github.com/apple/swift-atomics.git",
"state": {
"branch": null,
"revision": "cd142fd2f64be2100422d658e7411e39489da985",
"version": "1.2.0"
}
},
{
"package": "swift-collections",
"repositoryURL": "https://github.com/apple/swift-collections.git",
"state": {
"branch": null,
"revision": "3d2dc41a01f9e49d84f0a3925fb858bed64f702d",
"version": "1.1.2"
}
},
{
"package": "swift-nio",
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
"revision": "e4abde8be0e49dc7d66e6eed651254accdcd9533",
"version": "2.69.0"
}
},
{
"package": "swift-nio-transport-services",
"repositoryURL": "https://github.com/apple/swift-nio-transport-services",
"state": {
"branch": null,
"revision": "38ac8221dd20674682148d6451367f89c2652980",
"version": "1.21.0"
}
},
{
"package": "swift-system",
"repositoryURL": "https://github.com/apple/swift-system.git",
"state": {
"branch": null,
"revision": "d2ba781702a1d8285419c15ee62fd734a9437ff5",
"version": "1.3.2"
}
},
{
"package": "TreeSitter",
"repositoryURL": "https://github.com/tree-sitter/tree-sitter",
Expand Down
44 changes: 24 additions & 20 deletions Code.xcodeproj/xcshareddata/xcschemes/extension.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
buildForTesting = "NO"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "944EEBEF2563C381009D77FE"
Expand All @@ -35,6 +35,20 @@
ReferencedContainer = "container:Code.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "NO"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9419692E280316C7008AAEB2"
BuildableName = "CodeUI.app"
BlueprintName = "CodeUI"
ReferencedContainer = "container:Code.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
Expand Down Expand Up @@ -65,15 +79,6 @@
ReferencedContainer = "container:Code.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "944EEBEF2563C381009D77FE"
BuildableName = "Code.app"
BlueprintName = "Code"
ReferencedContainer = "container:Code.xcodeproj">
</BuildableReference>
</MacroExpansion>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand All @@ -83,16 +88,15 @@
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "944EEBEF2563C381009D77FE"
BuildableName = "Code.app"
BlueprintName = "Code"
BlueprintIdentifier = "94369AFB25E3B933008419A0"
BuildableName = "extension.appex"
BlueprintName = "extension"
ReferencedContainer = "container:Code.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
Expand Down
2 changes: 2 additions & 0 deletions CodeApp/CodeApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ios_system
struct CodeApp: App {
@StateObject var themeManager = ThemeManager()
let wasmService = WASMService()
let editorService = EditorService()

init() {
setup()
Expand All @@ -37,6 +38,7 @@ private func setup() {
wasmWebView.loadWorker()
initializeEnvironment()
Repository.initialize_libgit2()
AppExtensionService.shared.startServer()
}

private func versionNumberIncreased() -> Bool {
Expand Down
36 changes: 36 additions & 0 deletions CodeApp/Constants/LanguageService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// LanguageService.swift
// Code
//
// Created by Ken Chung on 09/08/2024.
//

import Foundation

class LanguageService {
struct Configuration {
let languageIdentifier: String
let extensions: [String]
let args: [String]
}

var candidateLanguageIdentifier: String? = nil

static let shared = LanguageService()
static let configurations: [Configuration] = [
Configuration(
languageIdentifier: "python",
extensions: ["py"],
args: ["jedi-language-server", "-v"]),
Configuration(
languageIdentifier: "java",
extensions: ["java"],
args: ["java", "-jar", "${JAVA_LSP_FAT_JAR_PATH}"]),
]

static func configurationFor(url: URL) -> Configuration? {
return LanguageService.configurations.first(where: {
$0.extensions.contains(url.pathExtension)
})
}
}
121 changes: 121 additions & 0 deletions CodeApp/Managers/AppExtensionService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// AppExtensionService.swift
// Code App
//
// Created by Ken Chung on 02/07/2024.
//

import Dynamic
import Foundation
import ios_system

class AppExtensionService: NSObject {
static let PORT = 50002
static let shared = AppExtensionService()
private var task: URLSessionWebSocketTask? = nil

func startServer() {
let BLE: AnyClass = (NSClassFromString("TlNFeHRlbnNpb24=".base64Decoded()!)!)
let ext = Dynamic(BLE).extensionWithIdentifier(
"thebaselab.VS-Code.extension", error: nil)
let frameworkDir = Bundle.main.privateFrameworksPath!
let frameworkDirBookmark = try! URL(fileURLWithPath: frameworkDir).bookmarkData()
let item = NSExtensionItem()
item.userInfo = [
"frameworksDirectoryBookmark": frameworkDirBookmark,
"port": AppExtensionService.PORT,
]
ext.setRequestInterruptionBlock(
{ uuid in
print("Extension server crashed, attempting to restart")
self.startServer()
} as RequestInterruptionBlock)

ext.beginExtensionRequestWithInputItems(
[item],
completion: { uuid in
let pid = ext.pid(forRequestIdentifier: uuid)
if let uuid = uuid {
print("Started extension request: \(uuid). Extension PID is \(pid)")
}
print("Extension server listening on 127.0.0.1:\(AppExtensionService.PORT)")
} as RequestBeginBlock)

}

func stopServer() {
let notificationName = CFNotificationName(
"com.thebaselab.code.node.stop" as CFString)
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
CFNotificationCenterPostNotification(
notificationCenter, notificationName, nil, nil, false)
}

func terminate() {
self.task?.cancel()
}

func prepareServer() async {
if LanguageService.shared.candidateLanguageIdentifier == nil { return }
stopServer()

try? await Task.sleep(nanoseconds: 1 * 1_000_000_000)
}

func call(
args: [String],
t_stdin: UnsafeMutablePointer<FILE>,
t_stdout: UnsafeMutablePointer<FILE>
) async throws {
await prepareServer()

defer {
self.task = nil
signal(SIGINT, SIG_DFL)
}

let signalCallback: sig_t = { signal in
// TODO: send real signal instead
AppExtensionService.shared.terminate()
}
signal(SIGINT, signalCallback)

let task = URLSession.shared.webSocketTask(
with: URL(string: "ws://127.0.0.1:\(String(AppExtensionService.PORT))/websocket")!)
self.task = task
task.resume()

let handle = FileHandle(fileDescriptor: fileno(t_stdin), closeOnDealloc: false)
handle.readabilityHandler = { fileHandle in
if let str = String(data: fileHandle.availableData, encoding: .utf8) {
Task {
try await task.send(.string(str))
print("Sending -> \(str)")
}
}
}

let frame = ExecutionRequestFrame(
args: args,
redirectStderr: true,
workingDirectoryBookmark: try? URL(
fileURLWithPath: FileManager.default.currentDirectoryPath
).bookmarkData(),
isLanguageService: false
)

try await task.send(.string(frame.stringRepresentation))

print("Sending -> \(frame.stringRepresentation)")

while let message = try? await task.receive() {
switch message {
case .string(let text):
print("Receiving <- \(text)")
fputs(text, t_stdout)
default:
continue
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ protocol EditorImplementationDelegate: AnyObject {
contentDidChangeForModelURL url: String, content: String, versionID: Int)
func editorImplementation(cursorPositionDidChange line: Int, column: Int)
func editorImplementation(onOpenURL url: String)
func editorImplementation(languageServerDidDisconnect languageIdentifier: String)

// Monaco specfic methods
func editorImplementation(markersDidUpdate markers: [MonacoEditorMarker])
Expand Down Expand Up @@ -138,6 +139,12 @@ protocol EditorImplementation: AnyObject {
func moveToPreviousDiff() async
func isEditorInDiffMode() async -> Bool

// Intellisense operations
func connectLanguageService(
serverURL: URL, serverArgs: [String], pwd: URL, languageIdentifier: String)
func disconnectLanguageService()
var isLanguageServiceConnected: Bool { get async }

// Monaco Editor operations
func _applyCustomShortcuts() async
func _toggleCommandPalatte() async
Expand Down
Loading
Loading