Tuist Project organisation, for editing in third party code editors with SourceKit-LSP

Question

Editing or developing a Tuist project in a third party code editors that utilises the SourceKit-LSP

Expectation

I expect the SourceKit-LSP to pick up the dependencies and so forth, like it does for a normal SPM project.
However, the only way I get the autocompletion or other LS Goodies in the manifest files, or the source files, is when I use tuist edit and tuist generate, (which is superb and very nice!). However if I open the file in other code editors, I get all these issues popping up, and sourcekit struggling to resolve the dependencies etc

Context

  • Tuist version: latest
  • Bare bone, blank Tuist project with one dependency
  • third party editors, Nova with Icarus, and Helix

Reproduction (mandatory for problems)

  • create a project by init, with ONE dependency
  • Open in third party editors
  • The manifest files will have issues due to dependency issues.
import ProjectDescription // for example
  • Add Alamofire as a dependency
  • Run tuist install
  • Include it in the main source code, and you will see issues regarding dependency resolution

My Current Hacky work around

  • I remove the Package.swift from Tuist/Package.swift and place it at the root ./
  • And also add the target, platform, dependency and product
  • run tuist install
  • run swift build

and everything seem to work fine in my third party editor

// ** Sample Package.swift at the root directory **\\ 

// swift-tools-version: 6.0
import PackageDescription

#if TUIST
    import struct ProjectDescription.PackageSettings

    let packageSettings = PackageSettings(
        // Customize the product types for specific package product
        // Default is .staticFramework
        productTypes: ["Alamofire": .framework]
//        productTypes: [:]
    )
#endif

let package = Package(
    name: "Playground",
    platforms: [.macOS(.v11)],
    products: [.library(name: "Playground", targets: ["PlaygroundApp"])],
    dependencies: [
        // Add your own dependencies here:
        .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
        // You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
    ],
    targets: [
        .target(name: "PlaygroundApp", dependencies: ["Alamofire"], path: "Playground/Sources/"),
    ]
)

Thanks!

1 Like

Hi @Alch3m1st

As you noted, the experience of editing your manifest feels degraded coming from editing a Package.swift.

I’m not very familiar with how code editors integrate with SourceKit-LSP. Still, if it works fine with Xcode projects, you should be able to integrate it with the project that Tuist generates for editing. We could explore what changes would be necessary to make that integration as smooth as possible.

If extensions don’t work well with Xcode projects, I’m afraid enabling the same experience outside of Xcode will be a bit tricky without a huge investment, which we can’t afford now.

1 Like

Ah! So I did a bit of digging, seems .xcodeproj etc are not used by the SourceKit-LSP directly. Even though Xcode also uses the LSP, it does some magic based on the manifest files putting everything in order, then kicking LSP somehow. :man_shrugging:

One last question! Is it really against convention (bad idea) if I bring Package.swift to the root dir and add a few details as described above? Basically, deleting the /Tuist dir.

What I realised is that, when I do swift build this way, the .swiftinterface file is cached somewhere for the sourcekit for the project.

The Tuist, build, generate as well as edit all seem to work fine as they use the Tuist manifest files such as Project.swift etc, and ignores all the extra bits I added :slight_smile:

If extensions don’t work well with Xcode projects, I’m afraid enabling the same experience outside of Xcode will be a bit tricky without a huge investment, which we can’t afford now.

Please not :laughing: ! The ideal is Apple just merging/buying Tuist, and scrap the ancient xcodeproj, xcodeworkspace etc! Or just fix the LSP, so it also parses and understands these directories…

// ** Sample Package.swift at the root directory **\\ 

// swift-tools-version: 6.0
import PackageDescription

#if TUIST
    import struct ProjectDescription.PackageSettings

    let packageSettings = PackageSettings(
        // Customize the product types for specific package product
        // Default is .staticFramework
        productTypes: ["Alamofire": .framework]
//        productTypes: [:]
    )
#endif

let package = Package(
    name: "Playground",
    platforms: [.macOS(.v11)],
    products: [.library(name: "Playground", targets: ["PlaygroundApp"])],
    dependencies: [
        // Add your own dependencies here:
        .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
        // You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
    ],
    targets: [
        .target(name: "PlaygroundApp", dependencies: ["Alamofire"], path: "Playground/Sources/"),
    ]
)

Not at all. In fact, having the Package.swift at the root is also a valid place for the file. So if it works for you, I recommend it to have it there. That’s the reason why all the commands work :).

:laughing: We’d love to take part in designing an evolution for that format. People are trying to use SwiftPM and Swift Packages to “escape” the issues with Xcode projects and workspaces, but it’s not the solution to the problem either, and they now find themselves having to reconcile the two worlds. We’ll see what the future holds, but they’ll have to do something if they want anything that depends on it (e.g. LLDB, SwiftUI previews…) to work reliably. And if they so, they should take the opportunity to decouple the layers so that people can create coding experiences outside of Xcode.

1 Like