swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.39k stars 10.34k forks source link

CursorInfo doesn’t provide a result if result builder contains an error #67216

Open adam-fowler opened 1 year ago

adam-fowler commented 1 year ago

Reported in swift-vscode repo https://github.com/swift-server/vscode-swift/issues/446

In the code below hover fails for Text, image and HStack inside the View resultBuilder while it works for everything outside of the resultBuilder.

import SwiftUI

struct ContentView: View {
    var image = Image("AltIconTest", bundle: .main)
    var body: some View {
        Text("I've been edited in VSCode. But can be run from both Xcode and VSCode.")
            .padding()
        image
        HStack {
            // none of these will appear when built with swift build & run as it doesn't compile asset catalogue
            // only appears when compiled and run from Xcode
            Image("Buddy").border(.blue)
            // will appear in Xcode version and xcodebuild version
            Image(packageResource: "Buddy", ofType: "png", from: .assetCatalog).border(.orange)
            // will only appear in xcodebuild version
            Image("Buddy", bundle: .module).border(.green).blur(radius: 0.1)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
ahoppen commented 1 year ago

rdar://102473561

ahoppen commented 1 year ago

This issue is not specific to SourceKit-LSP. The cursor info request that underlies hover does not provide results if the result builder body has an error. The solution here is to convert cursor info to the solver-based implementation as well but that might take a while.

The following reduced test case fails.

@resultBuilder
struct MyBuilder {
  static func buildBlock<Content>(_ components: Content...) -> Content {
    fatalError()
  }
  public static func buildExpression<Content>(_ content: Content) -> Content { return content }
}

struct ContentView {
  /// Some documentation
  var someInt: Int = 2

  @MyBuilder
  var body: Int {
    // RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):5 %s -- %s | %FileCheck %s
    someInt
    someInvalidRef
  }
}

// CHECK: source.lang.swift.ref.var.instance (11:7-11:14)