Фон
Подробное обсуждение этой проблемы см. В 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 зарегистрированный вывод выглядит следующим образом:
Имя каждого Clang cursor
отображается слева и каждый с отступом нижедетей курсора.Вы можете видеть, что ОДИН из этих детей является возвращаемым значением SBElementArray
.Вы также можете видеть, что значение return_type.kind
не определено.Скрипт проходит по дочерним элементам cursor
, пока не найдет тот, который не относится к типу parameter
.Он знает, что этот дочерний элемент является возвращаемым значением, извлекает его и пишет правильный код Swift.
В macOS Mojave возвращаемое значение больше не является дочерним элементом cursor
, как показано в выходных данных журнала:
Таким образом, в этом случае сценарий не находит возвращаемого значения, и функция теперь записана неправильно.
MyВопрос
Как это исправить?Я потратил часы на чтение документации Clang, поиск журналов изменений и т. Д. Я не могу понять (A) что изменилось и (B) каким должен быть новый подход для получения возвращаемого значения функции / метода.
Мне нужен кто-то, кто знает Clang лучше, чем я.Спасибо.