Связывание Python Libclang: получить возвращаемое значение метода ObjC - PullRequest
0 голосов
/ 04 октября 2018

Фон

Подробное обсуждение этой проблемы см. В https://github.com/tingraldi/SwiftScripting/issues/18.

Ссылка выше содержит длинный Python-скрипт, который переводит заголовок Objective-C File.hфайл в File.swift.Для этого он использует libclang для анализа файла и перевода AST в вывод Swift.

Вот сокращенное содержимое файла заголовка, который мы обрабатываем:

@interface FinderContainer : FinderItem

- (SBElementArray<FinderItem *> *) items;
- (SBElementArray<FinderContainer *> *) containers;

@end

Проблема

В macOS 10.13.6 с Xcode 9.4.1 и pip install clang==3.5 скрипт отлично работает и генерирует правильный вывод:

@objc public protocol FinderContainer: FinderItem {
    @objc optional func items() -> SBElementArray
    ...  // Truncated
}

HOWEVER, на macOS Mojave с Xcode10 установлены и те же pip install clang==3.5, возвращаемые значения функций отсутствуют:

@objc public protocol FinderContainer: FinderItem {
    @objc optional func items()
    ...  // Truncated
}

Примечание. Я протестировал clang 3.5 и последнюю версию: 6.0.0.2.Оба дают одинаковый результат.


Что происходит неправильно

Эта часть скрипта python использует объявление функции / метода и переводит его в Swift:

def emit_function(self, cursor):

    # ----LOGGING ADDITIONS -------------------------------------------------
    print(cursor.spelling)
    parameter_children_names = [child for child in cursor.get_children()]
    for x in parameter_children_names: print('   child --> ' + x.spelling)
    print('   result_type: ' + str(cursor.result_type.kind))
    # -----------------------------------------------------------------------

    func_name = safe_name(cursor.spelling.split(':')[0], keywords=general_keywords)
    parameter_cursors = [child for child in cursor.get_children() if child.kind == CursorKind.PARM_DECL]
    parameters = ['{}: {}'.format(arg_name(child.spelling, position=parameter_cursors.index(child)), type_for_type(child.type, as_arg=True))
                  for child in parameter_cursors]
    return_type = [child.type for child in cursor.get_children() if child.kind != CursorKind.PARM_DECL]
    if return_type:
        return_string = ' -> {}'.format(type_for_type(return_type[0]))
    else:
        return_string = ''

    self.emit_line('    @objc optional func {}({}){}{}'.format(
        func_name, ", ".join(parameters), return_string, self.line_comment(cursor)))

В macOS 10.13 зарегистрированный вывод выглядит следующим образом:

enter image description here

Имя каждого Clang cursor отображается слева и каждый с отступом нижедетей курсора.Вы можете видеть, что ОДИН из этих детей является возвращаемым значением SBElementArray.Вы также можете видеть, что значение return_type.kind не определено.Скрипт проходит по дочерним элементам cursor, пока не найдет тот, который не относится к типу parameter.Он знает, что этот дочерний элемент является возвращаемым значением, извлекает его и пишет правильный код Swift.

В macOS Mojave возвращаемое значение больше не является дочерним элементом cursor, как показано в выходных данных журнала:

enter image description here

Таким образом, в этом случае сценарий не находит возвращаемого значения, и функция теперь записана неправильно.


MyВопрос

Как это исправить?Я потратил часы на чтение документации Clang, поиск журналов изменений и т. Д. Я не могу понять (A) что изменилось и (B) каким должен быть новый подход для получения возвращаемого значения функции / метода.

Мне нужен кто-то, кто знает Clang лучше, чем я.Спасибо.

...