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

SourceKitten not reporting function substructure when only instance variable is changed #704

Closed
KaneCheshire opened this issue Sep 16, 2021 · 4 comments

Comments

@KaneCheshire
Copy link

KaneCheshire commented Sep 16, 2021

We have an issue with the latest version of SwiftLint and it seems as though it is because of a bug with SourceKitten itself. This has only manifested since updating to the latest version of SwiftLint, which is also using the latest version of SourceKitten.

TL;DR:

When provided with the following code:

class TotoTests: XCTestCase {
    var foo: String = ""

    override func setUp() {
        foo = "bar"
    }
}

SourceKitten does not report any substructure for the setUp() function, despite containing valid code in there.

More info

I've put together a test case which shows the issue:

func testBug() throws {
        let contents = "class TotoTests: XCTestCase {\n    var foo: String = \"\"\n    override func setUp() {\n        foo = \"bar\"\n    }\n}"

        let structure = try Structure(file: .init(contents: contents))
        let substructureArray = try XCTUnwrap(structure.dictionary["key.substructure"] as? [SourceKitRepresentable])
        let substructureDictionary = try XCTUnwrap(substructureArray.first as? [String : SourceKitRepresentable])

        let typeName = try XCTUnwrap(substructureDictionary["key.name"] as? String)
        XCTAssertEqual(typeName, "TotoTests")

        let typeSubstructureArray = try XCTUnwrap(substructureDictionary["key.substructure"] as? [SourceKitRepresentable])
        XCTAssertEqual(typeSubstructureArray.count, 2) // Only has one property and one function

        let propertySubstructureDictionary = try XCTUnwrap(typeSubstructureArray[0] as? [String: SourceKitRepresentable])
        let propertyName = try XCTUnwrap(propertySubstructureDictionary["key.name"] as? String)
        XCTAssertEqual(propertyName, "foo")

        let functionSubstructureDictionary = try XCTUnwrap(typeSubstructureArray[1] as? [String: SourceKitRepresentable])
        let functionName = try XCTUnwrap(functionSubstructureDictionary["key.name"] as? String)
        XCTAssertEqual(functionName, "setUp()")

        let functionContentsArray = try XCTUnwrap(functionSubstructureDictionary["key.substructure"] as? [SourceKitRepresentable])
        XCTAssertEqual(functionContentsArray.count, 1)
    }

Just to validate, if you change the contents to this:

let contents = "class TotoTests: XCTestCase {\n    var foo: String = \"\"\n    override func setUp() {\n        let foo = \"bar\"\n    }\n}"

Then the test passes fine. It's only an issue when setting an instance variable, rather than a local variable:

Screenshot 2021-09-16 at 11 44 54

Screenshot 2021-09-16 at 11 56 07

Additionally a similar issue was raised on the SwiftLint repo which I believe to be because of the same issue in SourceKitten.

I hope this helps debug, I don't know much more about SourceKitten but I can try and take a look at fixing too, but raising here because likely the code owner(s) will be able to fix it faster :)

@KaneCheshire
Copy link
Author

Oh I should also say, this is running the tests in Xcode 12.5.1, I haven't tried any other versions or toolchains.

@johnfairh
Copy link
Collaborator

The Structure API in SourceKitten makes a single query to SourceKit, source.request.editor.open, and returns the doc structure results without modification. You could check on the Swift nightly toolchain: if it's still a problem then the question -- something like "Assignment expressions missing from doc structure' belongs with the Swift project.

@KaneCheshire
Copy link
Author

Okay thanks for getting back to me, I notice it does pick up if you do foo = String() so guess it's a Swift issue then

@johnfairh
Copy link
Collaborator

Right -- just for interest, notice there you get just a source.lang.swift.expr.call inside the substructure which is the String() part -- the assignment part itself is not mentioned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants