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

key.bodyoffset's value is not correct when I use sourcekitten structure --file <file_path> to parse swift file structure #795

Closed
MayHeads opened this issue Nov 17, 2023 · 4 comments

Comments

@MayHeads
Copy link

Env

sourcekitten --version
0.34.1

CapModel.swift

@objcMembers class Simple :NSObject{
    
    
    static func loadData() {
        
    }
}

class CapModel {
    static var modeName: String = "CapModel"

    var name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    func addAge(index: Int) {
        self.age += 1
    }

    static func printStatic() {}
}
// 说明问题的严重性
class ItemModel {
    var item: String
    var interger: Int
    init(item: String, interger: Int) {
        self.item = item
        self.interger = interger
    }
    @objc func buttonAction() {
        print("----")
    }
    static func printStatic() {}
}

i use python to parse

def parse(file_path):
    command = f'sourcekitten structure --file "{file_path}"'
    output = subprocess.check_output(command, shell=True)
    z = json.loads(output.decode())
    y = json.dumps(z, indent=2)
    print(f"<output>:------>\n {y}")


if __name__ == "__main__":
    content = ''
    with open(file_path, 'r') as file:
        content = file.read()
    print(f"swift 文件的长度: {len(content)}")
    parse(file_path=file_path)

Log

swift 文件的长度: 652
<output>:------>
 {
  "key.diagnostic_stage": "source.diagnostic.stage.swift.parse",
  "key.length": 668,
  "key.offset": 0,
  "key.substructure": [
    {
      "key.accessibility": "source.lang.swift.accessibility.internal",
      "key.attributes": [
        {
          "key.attribute": "source.decl.attribute.objcMembers",
          "key.length": 12,
          "key.offset": 1
        }
      ],
      "key.bodylength": 55,
      "key.bodyoffset": 37,
      "key.elements": [
        {
          "key.kind": "source.lang.swift.structure.elem.typeref",
          "key.length": 8,
          "key.offset": 28
        }
      ],
      "key.inheritedtypes": [
        {
          "key.name": "NSObject"
        }
      ],
      "key.kind": "source.lang.swift.decl.class",
      "key.length": 79,
      "key.name": "Simple",
      "key.namelength": 6,
      "key.nameoffset": 20,
      "key.offset": 14,
      "key.substructure": [
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.bodylength": 14,
          "key.bodyoffset": 76,
          "key.kind": "source.lang.swift.decl.function.method.static",
          "key.length": 39,
          "key.name": "loadData()",
          "key.namelength": 10,
          "key.nameoffset": 64,
          "key.offset": 52
        }
      ]
    },
    {
      "key.accessibility": "source.lang.swift.accessibility.internal",
      "key.bodylength": 267,
      "key.bodyoffset": 111,
      "key.kind": "source.lang.swift.decl.class",
      "key.length": 284,
      "key.name": "CapModel",
      "key.namelength": 8,
      "key.nameoffset": 101,
      "key.offset": 95,
      "key.substructure": [
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.kind": "source.lang.swift.decl.var.static",
          "key.length": 40,
          "key.name": "modeName",
          "key.namelength": 8,
          "key.nameoffset": 127,
          "key.offset": 116,
          "key.setter_accessibility": "source.lang.swift.accessibility.internal",
          "key.typename": "String"
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.kind": "source.lang.swift.decl.var.instance",
          "key.length": 16,
          "key.name": "name",
          "key.namelength": 4,
          "key.nameoffset": 166,
          "key.offset": 162,
          "key.setter_accessibility": "source.lang.swift.accessibility.internal",
          "key.typename": "String"
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.kind": "source.lang.swift.decl.var.instance",
          "key.length": 12,
          "key.name": "age",
          "key.namelength": 3,
          "key.nameoffset": 187,
          "key.offset": 183,
          "key.setter_accessibility": "source.lang.swift.accessibility.internal",
          "key.typename": "Int"
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.bodylength": 53,
          "key.bodyoffset": 230,
          "key.kind": "source.lang.swift.decl.function.method.instance",
          "key.length": 84,
          "key.name": "init(name:age:)",
          "key.namelength": 28,
          "key.nameoffset": 200,
          "key.offset": 200,
          "key.substructure": [
            {
              "key.kind": "source.lang.swift.decl.var.parameter",
              "key.length": 12,
              "key.name": "name",
              "key.namelength": 4,
              "key.nameoffset": 205,
              "key.offset": 205,
              "key.typename": "String"
            },
            {
              "key.kind": "source.lang.swift.decl.var.parameter",
              "key.length": 8,
              "key.name": "age",
              "key.namelength": 3,
              "key.nameoffset": 219,
              "key.offset": 219,
              "key.typename": "Int"
            }
          ]
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.bodylength": 27,
          "key.bodyoffset": 315,
          "key.kind": "source.lang.swift.decl.function.method.instance",
          "key.length": 53,
          "key.name": "addAge(index:)",
          "key.namelength": 18,
          "key.nameoffset": 295,
          "key.offset": 290,
          "key.substructure": [
            {
              "key.kind": "source.lang.swift.decl.var.parameter",
              "key.length": 10,
              "key.name": "index",
              "key.namelength": 5,
              "key.nameoffset": 302,
              "key.offset": 302,
              "key.typename": "Int"
            }
          ]
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.bodylength": 0,
          "key.bodyoffset": 376,
          "key.kind": "source.lang.swift.decl.function.method.static",
          "key.length": 28,
          "key.name": "printStatic()",
          "key.namelength": 13,
          "key.nameoffset": 361,
          "key.offset": 349
        }
      ]
    },
    {
      "key.accessibility": "source.lang.swift.accessibility.internal",
      "key.bodylength": 241,
      "key.bodyoffset": 425,
      "key.kind": "source.lang.swift.decl.class",
      "key.length": 259,
      "key.name": "ItemModel",
      "key.namelength": 9,
      "key.nameoffset": 414,
      "key.offset": 408,
      "key.substructure": [
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.kind": "source.lang.swift.decl.var.instance",
          "key.length": 16,
          "key.name": "item",
          "key.namelength": 4,
          "key.nameoffset": 434,
          "key.offset": 430,
          "key.setter_accessibility": "source.lang.swift.accessibility.internal",
          "key.typename": "String"
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.kind": "source.lang.swift.decl.var.instance",
          "key.length": 17,
          "key.name": "interger",
          "key.namelength": 8,
          "key.nameoffset": 455,
          "key.offset": 451,
          "key.setter_accessibility": "source.lang.swift.accessibility.internal",
          "key.typename": "Int"
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.bodylength": 63,
          "key.bodyoffset": 508,
          "key.kind": "source.lang.swift.decl.function.method.instance",
          "key.length": 99,
          "key.name": "init(item:interger:)",
          "key.namelength": 33,
          "key.nameoffset": 473,
          "key.offset": 473,
          "key.substructure": [
            {
              "key.kind": "source.lang.swift.decl.var.parameter",
              "key.length": 12,
              "key.name": "item",
              "key.namelength": 4,
              "key.nameoffset": 478,
              "key.offset": 478,
              "key.typename": "String"
            },
            {
              "key.kind": "source.lang.swift.decl.var.parameter",
              "key.length": 13,
              "key.name": "interger",
              "key.namelength": 8,
              "key.nameoffset": 492,
              "key.offset": 492,
              "key.typename": "Int"
            }
          ]
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.attributes": [
            {
              "key.attribute": "source.decl.attribute.objc",
              "key.length": 5,
              "key.offset": 577
            }
          ],
          "key.bodylength": 27,
          "key.bodyoffset": 604,
          "key.kind": "source.lang.swift.decl.function.method.instance",
          "key.length": 49,
          "key.name": "buttonAction()",
          "key.namelength": 14,
          "key.nameoffset": 588,
          "key.offset": 583,
          "key.substructure": [
            {
              "key.bodylength": 6,
              "key.bodyoffset": 619,
              "key.kind": "source.lang.swift.expr.call",
              "key.length": 13,
              "key.name": "print",
              "key.namelength": 5,
              "key.nameoffset": 613,
              "key.offset": 613,
              "key.substructure": [
                {
                  "key.bodylength": 6,
                  "key.bodyoffset": 619,
                  "key.kind": "source.lang.swift.expr.argument",
                  "key.length": 6,
                  "key.offset": 619
                }
              ]
            }
          ]
        },
        {
          "key.accessibility": "source.lang.swift.accessibility.internal",
          "key.bodylength": 0,
          "key.bodyoffset": 664,
          "key.kind": "source.lang.swift.decl.function.method.static",
          "key.length": 28,
          "key.name": "printStatic()",
          "key.namelength": 13,
          "key.nameoffset": 649,
          "key.offset": 637
        }
      ]
    }
  ]
}

Question

  1. The length of the swift file's content is 652, but result of parse is 668

  2. The "key.name":"buttonAction()" "key.bodyoffset":604, i use this bodyoffset to divide content like below

    first = content[0:604]
    // result of the first
    class ItemModel {
        var item: String
        var interger: Int
        init(item: String, interger: Int) {
            self.item = item
            self.interger = interger
        }
        @objc func buttonAction() {
            print("
    
    
  3. In some simple data scenarios, there are no such problems if the content is below. Use the same way to parse, the result is right.

    class CapModel {
        static var modeName: String = "CapModel"
    
        var name: String
        var age: Int
        init(name: String, age: Int) {
            self.name = name
            self.age = age
        }
    
        func addAge(index: Int) {
            self.age += 1
        }
    
        static func printStatic() {}
    }
    
@MayHeads
Copy link
Author

The result printed in the second part of the Question is only the end, not the whole

@johnfairh
Copy link
Collaborator

SourceKit offsets are in bytes. Python len() etc. work on unicode characters. See eg. #635.

@MayHeads
Copy link
Author

@johnfairh Thanks :) this is my python code to resolve.

if __name__ == "__main__":
    content = ''
    with open(file_path, 'r') as file:
        content = file.read()
    byte_length = len(content.encode('utf-8'))
    # print(byte_length)
    # parse(file_path=file_path)
    byte_string = content.encode('utf-8')
    offset = 583 // replace your bodyoffset
    offset_byte_string = byte_string[0:offset]
    offset_string = offset_byte_string.decode('utf-8')
    print(offset_string)

@jpsim
Copy link
Owner

jpsim commented Nov 18, 2023

Closing since the initial question was answered

@jpsim jpsim closed this as completed Nov 18, 2023
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

3 participants