swiftlang / sourcekit-lsp

Language Server Protocol implementation for Swift and C-based languages
Apache License 2.0
3.3k stars 273 forks source link

Add Run/Debug CodeLens Support #1556

Closed plemarquand closed 2 months ago

plemarquand commented 3 months ago

Adds a response to the textDocument/codeLens request that returns two code lenses on the @main attribute of an application.

The LSP documentation breaks out the code lens requests into a Code Lens Request and a Code Lens Resolve Request, stating this is for performance reasons. However, there is no intensive work we need to do in order to resolve the commands for a CodeLens; we know them based on context at the time of discovery. For this reason we return resolved lenses with Commands for code lens requests.

A missing piece is only returning code lenses if the file resides in an executable product. To my knowledge Libraries and Plugins can't have an @main entrypoint and so it doesn't make sense to provide these code lenses in those contexts.

Some guidance is required on how to best determine if the textDocument in the request is within an executable product.

testCodeLensRequestWithInvalidProduct asserts that no lenses are returned with the @main attribute is on a file in a .executable, and is currently failing until this is addressed.

This will currently implement https://github.com/swiftlang/vscode-swift/issues/525 with no changes on the VS Code side.

plemarquand commented 3 months ago

One thing worth thinking about is whether or not command resolution should/could happen in the editor. I don't really like that sourcekit-lsp would have the "run" and "debug" commands hard coded within it. The editor may have more context about what commands it can run on a @main annotation.

A better flow might be that the LSP responds with a CodeLens for a range/uri annotated what type of lens it is (using CodeLens.data?). The client can then resolve the CodeLens command.

A technical limitation of the spec here is that if the server responds with one CodeLens then resolution response produces only one corresponding CodeLens with a command. Turning that one CodeLens response in to two (run + debug) doesn't seem straightforward.

Also CodeLens.data is a property of CodeLens in sourcekit-lsp but data isn't in the LSP spec, which would make using it to determine what type of CodeLens we're resolving in the client non standard.

plemarquand commented 2 months ago

@ahoppen I've updated the PR so that SourceKit-LSP accepts a new field in the client initializationOptions. It contains a dictionary where the key is the lens name recognized by SourceKit-LSP and the value is the command as recognized by the client.

I set it up this way so that the LSP doesn't make an assumption about the names of commands that the client can support, as they're not guaranteed to be named swift.run/swift.debug on the client side, though they are in VS Code. This may be overkill though, so I'm interested in your thoughts.

initializationOptions: {
    "textDocument/codeLens": {
        supportedCommands: {
            "swift.run": "clientCommandName_Run",
            "swift.debug": "clientCommandName_Debug",
        }
    }
}
ahoppen commented 2 months ago

@swift-ci Please test

plemarquand commented 2 months ago

@ahoppen apologies, only ran the linter on Sources not Tests.

ahoppen commented 2 months ago

@swift-ci Please test

ahoppen commented 2 months ago

@swift-ci Please test Windows

ahoppen commented 2 months ago

@swift-ci Please test

ahoppen commented 2 months ago

@swift-ci Please test Windows