Properly support interop with headers generated by Swift

These headers contain `external_source_symbol(..., generated_declaration)`
attributes, making clang indexer to ignore the declarations.
Add an additional AST pass to ensure that all Objective-C classes and
protocols get found.

See https://github.com/JetBrains/kotlin-native/issues/1841#issuecomment-411346727
This commit is contained in:
Svyatoslav Scherbina
2018-09-17 10:08:26 +03:00
committed by SvyatoslavScherbina
parent 446bacbe7a
commit 4ec1ec05cf
2 changed files with 33 additions and 16 deletions
@@ -122,10 +122,6 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
return library.headerToIdMapper.getHeaderId(filePath) return library.headerToIdMapper.getHeaderId(filePath)
} }
private fun getContainingFile(cursor: CValue<CXCursor>): CXFile? {
return clang_getCursorLocation(cursor).getContainingFile()
}
private fun getLocation(cursor: CValue<CXCursor>): Location { private fun getLocation(cursor: CValue<CXCursor>): Location {
val headerId = getHeaderId(getContainingFile(cursor)) val headerId = getHeaderId(getContainingFile(cursor))
return Location(headerId) return Location(headerId)
@@ -737,12 +733,8 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
} }
} }
CXIdxEntity_ObjCClass -> { CXIdxEntity_ObjCClass -> if (cursor.kind != CXCursorKind.CXCursor_ObjCClassRef /* not a forward declaration */) {
if (isAvailable(cursor) && indexObjCClass(cursor)
cursor.kind != CXCursorKind.CXCursor_ObjCClassRef /* not a forward declaration */) {
getObjCClassAt(cursor)
}
} }
CXIdxEntity_ObjCCategory -> { CXIdxEntity_ObjCCategory -> {
@@ -751,12 +743,8 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
} }
} }
CXIdxEntity_ObjCProtocol -> { CXIdxEntity_ObjCProtocol -> if (cursor.kind != CXCursorKind.CXCursor_ObjCProtocolRef /* not a forward declaration */) {
if (isAvailable(cursor) && indexObjCProtocol(cursor)
cursor.kind != CXCursorKind.CXCursor_ObjCProtocolRef /* not a forward declaration */) {
getObjCProtocolAt(cursor)
}
} }
CXIdxEntity_ObjCProperty -> { CXIdxEntity_ObjCProperty -> {
@@ -791,6 +779,18 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
} }
} }
fun indexObjCClass(cursor: CValue<CXCursor>) {
if (isAvailable(cursor)) {
getObjCClassAt(cursor)
}
}
fun indexObjCProtocol(cursor: CValue<CXCursor>) {
if (isAvailable(cursor)) {
getObjCProtocolAt(cursor)
}
}
private fun getFunction(cursor: CValue<CXCursor>): FunctionDecl { private fun getFunction(cursor: CValue<CXCursor>): FunctionDecl {
val name = clang_getCursorSpelling(cursor).convertAndDispose() val name = clang_getCursorSpelling(cursor).convertAndDispose()
val returnType = convertType(clang_getCursorResultType(cursor), clang_getCursorResultTypeAttributes(cursor)) val returnType = convertType(clang_getCursorResultType(cursor), clang_getCursorResultTypeAttributes(cursor))
@@ -920,6 +920,18 @@ private fun indexDeclarations(nativeIndex: NativeIndexImpl) {
} }
} }
}) })
visitChildren(clang_getTranslationUnitCursor(translationUnit)) { cursor, _ ->
val file = getContainingFile(cursor)
if (file in headers && nativeIndex.library.includesDeclaration(cursor)) {
when (cursor.kind) {
CXCursorKind.CXCursor_ObjCInterfaceDecl -> nativeIndex.indexObjCClass(cursor)
CXCursorKind.CXCursor_ObjCProtocolDecl -> nativeIndex.indexObjCProtocol(cursor)
else -> {}
}
}
CXChildVisitResult.CXChildVisit_Continue
}
} finally { } finally {
clang_disposeTranslationUnit(translationUnit) clang_disposeTranslationUnit(translationUnit)
} }
@@ -545,6 +545,11 @@ internal fun CValue<CXSourceLocation>.getContainingFile(): CXFile? = memScoped {
fileVar.value fileVar.value
} }
@JvmName("getFileContainingCursor")
internal fun getContainingFile(cursor: CValue<CXCursor>): CXFile? {
return clang_getCursorLocation(cursor).getContainingFile()
}
private fun createVfsOverlayFileContents(virtualPathToReal: Map<Path, Path>): ByteArray { private fun createVfsOverlayFileContents(virtualPathToReal: Map<Path, Path>): ByteArray {
val overlay = clang_VirtualFileOverlay_create(0) val overlay = clang_VirtualFileOverlay_create(0)