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

Is it possible to generate both the Swift and Objective-C signature for a token? #353

Closed
jverkoey opened this issue Nov 11, 2015 · 5 comments
Assignees
Milestone

Comments

@jverkoey
Copy link
Collaborator

Asking in case anyone knows the answer already, but digging in right now :)

@jpsim
Copy link
Collaborator

jpsim commented Nov 11, 2015

The very very first version of jazzy used an internal binary to do this called sourcekitd-test that shipped with the first two betas of Xcode 6 IIRC: https://github.com/realm/jazzy/blob/0.0.4/bin/generate_swift_header.sh

This first version of jazzy was designed to just build docs for Objective-C headers with both Swift and Objective-C interface declarations.

When this private binary disappeared, I shifted gears with jazzy to just generate docs for Swift projects. I've never actively tried to reproduce the original behavior of generating the Swift interface to an Objective-C declaration, but it would most certainly be done via SourceKit.

@jpsim
Copy link
Collaborator

jpsim commented Nov 11, 2015

Running Xcode with the SOURCEKIT_LOGGING=3 environment variable just now to see what XPC request is sent when requesting the Swift interface to an Objective-C file, here's what the request looks like:

{
  key.request: source.request.editor.open.interface.header,
  key.name: "6FFBEC1C-2E70-43C9-BE02-3F9CF2F7A313",
  key.filepath: "/Users/jp/Projects/SourceKitten/Source/SourceKittenFramework/clang-c/Documentation.h",
  key.compilerargs: [
    "-x",
    "objective-c",
    "/Users/jp/Projects/SourceKitten/Source/SourceKittenFramework/clang-c/Documentation.h",
    "-isysroot",
    "/Applications/Xcode-7.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk"
  ]
}

and the response:

{
  key.sourcetext: "/*==-- clang-c/Documentation.h - Utilities for comment processing -*- C -*-===*\
|*                                                                            *|
|*                     The LLVM Compiler Infrastructure                       *|
|*                                                                            *|
|* This file is distributed under the University of Illinois Open Source      *|
|* License. See LICENSE.TXT for details.                                      *|
|*                                                                            *|
|*===----------------------------------------------------------------------===*|
|*                                                                            *|
|* This header provides a supplementary interface for inspecting              *|
|* documentation comments.                                                    *|
|*                                                                            *|
\*===----------------------------------------------------------------------===*/

/**
 * \defgroup CINDEX_COMMENT Comment introspection
 *
 * The routines in this group provide access to information in documentation
 * comments. These facilities are distinct from the core and may be subject to
 * their own schedule of stability and deprecation.
 *
 * @{
 */

/**
 * \brief A parsed comment.
 */
public struct CXComment {
    public var ASTNode: UnsafePointer<Void>
    public var TranslationUnit: Int32
    public init()
    public init(ASTNode: UnsafePointer<Void>, TranslationUnit: Int32)
}

// this goes on for a while
// ...

/**
 * \brief Convert a given full parsed comment to an XML document.
 *
 * A Relax NG schema for the XML can be found in comment-xml-schema.rng file
 * inside clang source tree.
 *
 * \param Comment a \c CXComment_FullComment AST node.
 *
 * \returns string containing an XML document.
 */
public var CXString: Int32
",
  key.annotations: [
    {
      key.kind: source.lang.swift.ref.struct,
      key.offset: 1419,
      key.length: 13,
      key.is_system: 1
    },
    {
      key.kind: source.lang.swift.ref.typealias,
      key.offset: 1433,
      key.length: 4,
      key.is_system: 1
    },
    {
      key.kind: source.lang.swift.ref.struct,
      key.offset: 1471,
      key.length: 5,
      key.is_system: 1
    },

// also goes on for a while
// ...

    {
      key.kind: source.lang.swift.ref.struct,
      key.offset: 13118,
      key.length: 5,
      key.is_system: 1
    }
  ],
  key.syntaxmap: [
    {
      key.kind: source.lang.swift.syntaxtype.comment,
      key.offset: 0,
      key.length: 1052
    },
    {
      key.kind: source.lang.swift.syntaxtype.doccomment,
      key.offset: 1054,
      key.length: 277
    },

// etc...


    {
      key.kind: source.lang.swift.syntaxtype.identifier,
      key.offset: 13108,
      key.length: 8
    },
    {
      key.kind: source.lang.swift.syntaxtype.typeidentifier,
      key.offset: 13118,
      key.length: 5
    }
  ],
  key.substructure: [
    {
      key.kind: source.lang.swift.decl.struct,
      key.accessibility: source.lang.swift.accessibility.public,
      key.name: "CXComment",
      key.offset: 1376,
      key.length: 190,
      key.nameoffset: 1383,
      key.namelength: 9,
      key.bodyoffset: 1394,
      key.bodylength: 171,
      key.substructure: [
        {
          key.kind: source.lang.swift.decl.var.instance,
          key.accessibility: source.lang.swift.accessibility.public,
          key.setter_accessibility: source.lang.swift.accessibility.public,
          key.name: "ASTNode",
          key.offset: 1406,
          key.length: 32,
          key.typename: "UnsafePointer<Void>",
          key.nameoffset: 1410,
          key.namelength: 7
        },
        {
          key.kind: source.lang.swift.decl.var.instance,
          key.accessibility: source.lang.swift.accessibility.public,
          key.setter_accessibility: source.lang.swift.accessibility.public,
          key.name: "TranslationUnit",
          key.offset: 1450,
          key.length: 26,
          key.typename: "Int32",
          key.nameoffset: 1454,
          key.namelength: 15
        },
        {
          key.kind: source.lang.swift.decl.function.method.instance,
          key.accessibility: source.lang.swift.accessibility.public,
          key.name: "init()",
          key.offset: 1488,
          key.length: 6,
          key.nameoffset: 1488,
          key.namelength: 6
        },

// etc...

    {
      key.kind: source.lang.swift.decl.var.global,
      key.accessibility: source.lang.swift.accessibility.public,
      key.setter_accessibility: source.lang.swift.accessibility.public,
      key.name: "CXString",
      key.offset: 13104,
      key.length: 19,
      key.typename: "Int32",
      key.nameoffset: 13108,
      key.namelength: 8
    }
  ]
}

So this is kind of promising, but sadly I don't see a surefire way of mapping from an Objective-C declaration to its Swift declaration. Only to get the Swift interface for a full Objective-C header.

However, if I option-click one of the generated tokens, the following XPC request is sent to SourceKit:

sourcekit: [2:sourcekitd_send_request-before:1295:151.0139] {
  key.request: source.request.cursorinfo,
  key.compilerargs: [
    "-x",
    "objective-c",
    "/Users/jp/Projects/SourceKitten/Source/SourceKittenFramework/clang-c/Index.h",
    "-isysroot",
    "/Applications/Xcode-7.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk"
  ],
  key.offset: 96274,
  key.sourcefile: "F5592DAF-75FC-407D-A282-9278702EA348"
}

which then generates this response:

sourcekit: [2:sourcekitd_send_request-after:48971:151.0153] {
  key.kind: source.lang.swift.decl.function.free,
  key.name: "clang_visitChildrenWithBlock(_:_:)",
  key.usr: "c:@F@clang_visitChildrenWithBlock",
  key.doc.full_as_xml: "<Function file="/Users/jp/Projects/SourceKitten/Source/SourceKittenFramework/clang-c/Index.h" line="3560" column="10"><Name>clang_visitChildrenWithBlock</Name><USR>c:@F@clang_visitChildrenWithBlock</USR><Declaration>func clang_visitChildrenWithBlock(parent: CXCursor, _ block: CXCursorVisitorBlock!) -> UInt32</Declaration><Abstract><Para> Visits the children of a cursor using the specified block.  Behaves identically to clang_visitChildren() in all other respects.</Para></Abstract></Function>",
  key.filepath: "/Users/jp/Projects/SourceKitten/Source/SourceKittenFramework/clang-c/Index.h",
  key.offset: 119462,
  key.length: 28,
  key.typename: "(CXCursor, CXCursorVisitorBlock!) -> UInt32",
  key.annotated_decl: "<Declaration>func clang_visitChildrenWithBlock(parent: <Type usr="c:@SA@CXCursor">CXCursor</Type>, _ block: <Type usr="c:Index.h@T@CXCursorVisitorBlock">CXCursorVisitorBlock</Type>!) -&gt; <Type usr="s:VSs6UInt32">UInt32</Type></Declaration>"
}

Which leads me to believe we should be able to map from Objective-C USR to the Swift USR if we perform the necessary shenanigans.

@jverkoey
Copy link
Collaborator Author

Hm, thanks for the background :) Looks like additional shenanigans are indeed required.

@jpsim
Copy link
Collaborator

jpsim commented Nov 11, 2015

Proof of concept: jpsim/SourceKitten#95

@jpsim
Copy link
Collaborator

jpsim commented Apr 6, 2016

Closing as a duplicate of #136.

@jpsim jpsim closed this as completed Apr 6, 2016
@pigeon-archive pigeon-archive modified the milestone: The Past Nov 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants