├── .gitignore ├── .travis.yml ├── LICENSE ├── Package.swift ├── README.md ├── Sources ├── Clang │ ├── Availability.swift │ ├── CType.swift │ ├── CTypes.swift │ ├── ClangError.swift │ ├── Comment.swift │ ├── Cursor.swift │ ├── Cursors.swift │ ├── Diagnostic.swift │ ├── EvalResult.swift │ ├── File.swift │ ├── FunctionDecl.swift │ ├── Index.swift │ ├── Language.swift │ ├── NameRefOptions.swift │ ├── Token.swift │ ├── TranslationUnit.swift │ └── Utilities.swift └── cclang │ ├── module.modulemap │ └── shim.h ├── Tests ├── ClangTests │ └── ClangTests.swift └── LinuxMain.swift ├── docs ├── Classes.html ├── Classes │ ├── Index.html │ └── TranslationUnit.html ├── Enums.html ├── Enums │ ├── CXXAccessSpecifierKind.html │ ├── CallingConvention.html │ ├── ChildVisitResult.html │ ├── ClangError.html │ ├── DiagnosticSeverity.html │ ├── EvalResult.html │ ├── Language.html │ ├── LoadDiagError.html │ ├── ParamPassDirection.html │ ├── RefQualifier.html │ ├── StorageClass.html │ ├── TemplateArgumentKind.html │ ├── TypeLayoutError.html │ └── VisibilityKind.html ├── Extensions.html ├── Extensions │ ├── CXCursor.html │ ├── CXType.html │ ├── ClangCursorBacked.html │ ├── ClangTypeBacked.html │ ├── MacroCursor.html │ ├── MethodDecl.html │ ├── RecordDecl.html │ └── TypeAliasCursor.html ├── Functions.html ├── Protocols.html ├── Protocols │ ├── CType.html │ ├── Comment.html │ ├── Cursor.html │ └── Token.html ├── Structs.html ├── Structs │ ├── Availability.html │ ├── BlockCommandComment.html │ ├── CallExpr.html │ ├── CommentToken.html │ ├── ConstantArrayType.html │ ├── DiagnosticDisplayOptions.html │ ├── EnumConstantDecl.html │ ├── EnumDecl.html │ ├── File.html │ ├── FullComment.html │ ├── FunctionDecl.html │ ├── GlobalOptions.html │ ├── HTMLAttribute.html │ ├── HTMLEndTagComment.html │ ├── HTMLStartTagComment.html │ ├── IdentifierToken.html │ ├── InclusionDirective.html │ ├── IncompleteArrayType.html │ ├── InlineCommandComment.html │ ├── KeywordToken.html │ ├── LiteralToken.html │ ├── NameRefOptions.html │ ├── ObjCMessageExpr.html │ ├── ObjCPropertyAttributes.html │ ├── ParagraphComment.html │ ├── ParamCommandComment.html │ ├── PlatformAvailability.html │ ├── PointerType.html │ ├── PunctuationToken.html │ ├── RecordType.html │ ├── SourceLocation.html │ ├── SourceRange.html │ ├── TParamCommandComment.html │ ├── TextComment.html │ ├── TranslationUnitOptions.html │ ├── UniqueFileID.html │ ├── VariableArrayType.html │ ├── VerbatimBlockCommandComment.html │ ├── VerbatimBlockLineComment.html │ ├── VerbatimLineComment.html │ └── Version.html ├── badge.svg ├── css │ ├── highlight.css │ └── jazzy.css ├── docsets │ ├── Clang.docset │ │ └── Contents │ │ │ ├── Info.plist │ │ │ └── Resources │ │ │ ├── Documents │ │ │ ├── Classes.html │ │ │ ├── Classes │ │ │ │ ├── Index.html │ │ │ │ └── TranslationUnit.html │ │ │ ├── Enums.html │ │ │ ├── Enums │ │ │ │ ├── CXXAccessSpecifierKind.html │ │ │ │ ├── CallingConvention.html │ │ │ │ ├── ChildVisitResult.html │ │ │ │ ├── ClangError.html │ │ │ │ ├── DiagnosticSeverity.html │ │ │ │ ├── EvalResult.html │ │ │ │ ├── Language.html │ │ │ │ ├── LoadDiagError.html │ │ │ │ ├── ParamPassDirection.html │ │ │ │ ├── RefQualifier.html │ │ │ │ ├── StorageClass.html │ │ │ │ ├── TemplateArgumentKind.html │ │ │ │ ├── TypeLayoutError.html │ │ │ │ └── VisibilityKind.html │ │ │ ├── Extensions.html │ │ │ ├── Extensions │ │ │ │ ├── CXCursor.html │ │ │ │ ├── CXType.html │ │ │ │ ├── ClangCursorBacked.html │ │ │ │ ├── ClangTypeBacked.html │ │ │ │ ├── MacroCursor.html │ │ │ │ ├── MethodDecl.html │ │ │ │ ├── RecordDecl.html │ │ │ │ └── TypeAliasCursor.html │ │ │ ├── Functions.html │ │ │ ├── Protocols.html │ │ │ ├── Protocols │ │ │ │ ├── CType.html │ │ │ │ ├── Comment.html │ │ │ │ ├── Cursor.html │ │ │ │ └── Token.html │ │ │ ├── Structs.html │ │ │ ├── Structs │ │ │ │ ├── Availability.html │ │ │ │ ├── BlockCommandComment.html │ │ │ │ ├── CallExpr.html │ │ │ │ ├── CommentToken.html │ │ │ │ ├── ConstantArrayType.html │ │ │ │ ├── DiagnosticDisplayOptions.html │ │ │ │ ├── EnumConstantDecl.html │ │ │ │ ├── EnumDecl.html │ │ │ │ ├── File.html │ │ │ │ ├── FullComment.html │ │ │ │ ├── FunctionDecl.html │ │ │ │ ├── GlobalOptions.html │ │ │ │ ├── HTMLAttribute.html │ │ │ │ ├── HTMLEndTagComment.html │ │ │ │ ├── HTMLStartTagComment.html │ │ │ │ ├── IdentifierToken.html │ │ │ │ ├── InclusionDirective.html │ │ │ │ ├── IncompleteArrayType.html │ │ │ │ ├── InlineCommandComment.html │ │ │ │ ├── KeywordToken.html │ │ │ │ ├── LiteralToken.html │ │ │ │ ├── NameRefOptions.html │ │ │ │ ├── ObjCMessageExpr.html │ │ │ │ ├── ObjCPropertyAttributes.html │ │ │ │ ├── ParagraphComment.html │ │ │ │ ├── ParamCommandComment.html │ │ │ │ ├── PlatformAvailability.html │ │ │ │ ├── PointerType.html │ │ │ │ ├── PunctuationToken.html │ │ │ │ ├── RecordType.html │ │ │ │ ├── SourceLocation.html │ │ │ │ ├── SourceRange.html │ │ │ │ ├── TParamCommandComment.html │ │ │ │ ├── TextComment.html │ │ │ │ ├── TranslationUnitOptions.html │ │ │ │ ├── UniqueFileID.html │ │ │ │ ├── VariableArrayType.html │ │ │ │ ├── VerbatimBlockCommandComment.html │ │ │ │ ├── VerbatimBlockLineComment.html │ │ │ │ ├── VerbatimLineComment.html │ │ │ │ └── Version.html │ │ │ ├── css │ │ │ │ ├── highlight.css │ │ │ │ └── jazzy.css │ │ │ ├── img │ │ │ │ ├── carat.png │ │ │ │ ├── dash.png │ │ │ │ └── gh.png │ │ │ ├── index.html │ │ │ ├── js │ │ │ │ ├── jazzy.js │ │ │ │ └── jquery.min.js │ │ │ └── search.json │ │ │ └── docSet.dsidx │ └── Clang.tgz ├── img │ ├── carat.png │ ├── dash.png │ └── gh.png ├── index.html ├── js │ ├── jazzy.js │ └── jquery.min.js ├── search.json └── undocumented.json ├── input_tests ├── inclusion-header.h ├── inclusion.c ├── index-action.c ├── init-ast.c ├── is-from-main-file.c ├── locations.c ├── reparse.c └── unsaved-file.c └── utils └── make-pkgconfig.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /build 4 | /Packages 5 | /*.xcodeproj 6 | Xcode/Modules/cclang/module.modulemap 7 | *.xcuserdatad 8 | *.resolved 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | global: 3 | - LC_CTYPE=en_US.UTF-8 4 | matrix: 5 | include: 6 | - os: osx 7 | language: objective-c 8 | osx_image: xcode10.2 9 | before_install: 10 | - export PATH=/usr/local/opt/llvm/bin:"${PATH}" 11 | - brew install llvm 12 | - sudo swift utils/make-pkgconfig.swift 13 | script: 14 | - swift test 15 | notifications: 16 | slack: 17 | secure: ek/+U+e44bqP8+QCHojy2LhrN9iwY3N/TNNqNG5FZrp09Vidrd5KXWJOXFxlGrpeWdgTpi089YbEdTfxpcDIudUqDqLwPzS7wePiG2cEC1OT6l3yrhI4AvOe7EsNSOX8gzkuEnmrZVHwLLGe7JeR7JIQKoHMZsBcPYDnO8kRP0Ei3zOh47YUn75SE87egAgZOVBDbZYO3GWRa4WX64s8gaQYQ9a7EoUY0oX9rQ48FJs3rmEIhvIXdcOj9bGX7+o0j7l+IFial/Qh+B6bp4XkZU/tUVP6cuNVI1vxE1weVGCBhgt5wLhXTMewzoE5D1IgMZHVuzIBcDbBthSzQRttLSlYar6xTjXtRtOnb8tqZMWfUj3HBYCFYqtz7PGnZ3IflEVsPJW6tgSsoeB6egjzb8APP9mvhm8+zb1jQG1dqXLWErMjWqhlyPVPmHrxU2w/OLWLAJPY94GVmLnSuOw2pSz41spuEY80JcVVzoRbAOQWrwAujq2S3k93yvKpGq4eaT72Mt8g1CyZesByvzcLk99LEJSpqOIxUqXBd4RwHhay/sq8LllyyqY8ORsxEgwQluOAjEhATO/t/HUsu2ndn1k38U1c4HqXW7FDs1hffYEzZ/PGxciCS6Vt1bfST+iq34pzqpanENQCnX6mSR+D+M7mHlCWdsUihmxEcs5knuM= 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Trill Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "Clang", 6 | products: [ 7 | .library( 8 | name: "Clang", 9 | targets: ["Clang"]) 10 | ], 11 | dependencies: [ ], 12 | targets: [ 13 | .systemLibrary( 14 | name: "cclang", 15 | pkgConfig: "cclang", 16 | providers: [ 17 | .brew(["llvm"]), 18 | ]), 19 | .target( 20 | name: "Clang", 21 | dependencies: ["cclang"]), 22 | .testTarget( 23 | name: "ClangTests", 24 | dependencies: ["Clang"]) 25 | ] 26 | ) 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ClangSwift 2 | [![Documentation](https://cdn.rawgit.com/llvm-swift/ClangSwift/master/docs/badge.svg)](https://llvm-swift.github.io/ClangSwift) 3 | 4 | ClangSwift aims to be a Swifty wrapper for the `libclang` C API, much like 5 | [LLVMSwift](https://github.com/llvm-swift/LLVMSwift). 6 | 7 | It's still heavily in development, and is nowhere near complete. 8 | Check back for updates! 9 | 10 | # Authors 11 | 12 | - Harlan Haskins ([@harlanhaskins](https://github.com/harlanhaskins)) 13 | - Robert Widmann ([@CodaFi](https://github.com/CodaFi)) 14 | 15 | # License 16 | 17 | ClangSwift is released under the MIT License, a copy of which is included 18 | in this repo. 19 | -------------------------------------------------------------------------------- /Sources/Clang/Availability.swift: -------------------------------------------------------------------------------- 1 | #if SWIFT_PACKAGE 2 | import cclang 3 | #endif 4 | 5 | /// Describes the availability of a given declaration for each platform. 6 | public struct Availability { 7 | /// Whether this declaration is unconditionally deprecated for all platforms. 8 | public let alwaysDeprecated: Bool 9 | 10 | /// The message to display when alerting someone of this deprecated 11 | /// declaration. 12 | public let deprecationMessage: String? 13 | 14 | /// Whether this declaration is unconditionally unavailable. 15 | public let alwaysUnavailable: Bool 16 | 17 | /// The message to display when alerting someone of this unavailable 18 | /// declaration. 19 | public let unavailableMessage: String? 20 | 21 | /// The specific availability for all platforms specified for this 22 | /// declaration. 23 | public let platforms: [PlatformAvailability] 24 | } 25 | 26 | /// Describes a version number of the form `..`. 27 | public struct Version { 28 | /// The major version number, e.g., the '10' in '10.7.3'. 29 | public let major: Int 30 | 31 | /// The minor version number, e.g., the '7' in '10.7.3'. This value will be 32 | /// 0 if no minor version number was provided, e.g., for version '10'. 33 | public let minor: Int 34 | 35 | /// The subminor version number, e.g., the '3' in '10.7.3'. This value will 36 | /// be 0 if no minor or subminor version number was provided, e.g., 37 | /// in version '10' or '10.7'. 38 | public let subminor: Int 39 | 40 | /// Represents a version number for 0.0.0. 41 | public static let zero = Version(major: 0, minor: 0, subminor: 0) 42 | 43 | 44 | /// Creates a version with the specified major, minor, and subminor versions. 45 | /// 46 | /// - Parameters: 47 | /// - major: The major version, e.g. "10" in "10.3.1" 48 | /// - minor: The minor version, e.g. "3" in "10.3.1" 49 | /// - subminor: The subminor version, e.g. "1" in "10.3.1" 50 | public init(major: Int, minor: Int, subminor: Int) { 51 | self.major = major 52 | self.minor = minor 53 | self.subminor = subminor 54 | } 55 | 56 | internal init?(clang: CXVersion) { 57 | guard clang.Major >= 0 else { return nil } 58 | self.major = Int(clang.Major) 59 | self.minor = max(Int(clang.Minor), 0) 60 | self.subminor = max(Int(clang.Subminor), 0) 61 | } 62 | } 63 | 64 | /// Describes the availability of a given entity on a particular 65 | /// platform, e.g., a particular class might 66 | /// only be available on Mac OS 10.7 or newer. 67 | public struct PlatformAvailability { 68 | /// A string that describes the platform for which this structure 69 | /// provides availability information. 70 | public let platform: String 71 | 72 | /// The version number in which this entity was introduced. 73 | public let introduced: Version 74 | 75 | /// The version number in which this entity was deprecated (but is 76 | /// still available). 77 | public let deprecated: Version? 78 | 79 | /// The version number in which this entity was obsoleted, and therefore 80 | /// is no longer available. 81 | public let obsoleted: Version? 82 | 83 | /// Whether the entity is unconditionally unavailable on this platform. 84 | public let unavailable: Bool 85 | 86 | /// An optional message to provide to a user of this API, e.g., to 87 | /// suggest replacement APIs. 88 | public let message: String? 89 | 90 | internal init(clang: CXPlatformAvailability) { 91 | // We have to dispose this whole structure at once with a call to 92 | // clang_disposeCXPlatformAvailability, so we can't dispose the 93 | // individual strings inside. 94 | self.platform = clang.Platform.asSwiftNoDispose() 95 | self.introduced = Version(clang: clang.Introduced) ?? .zero 96 | self.deprecated = Version(clang: clang.Deprecated) 97 | self.obsoleted = Version(clang: clang.Obsoleted) 98 | self.unavailable = clang.Unavailable != 0 99 | self.message = clang.Message.asSwiftOptionalNoDispose() 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Sources/Clang/CType.swift: -------------------------------------------------------------------------------- 1 | #if SWIFT_PACKAGE 2 | import cclang 3 | #endif 4 | 5 | /// The type of an element in the abstract syntax tree. 6 | public protocol CType: CustomStringConvertible { 7 | /// Converts the receiver to a `CXType` to be consumed by the libclang APIs. 8 | func asClang() -> CXType 9 | } 10 | 11 | public enum TypeLayoutError: Error { 12 | /// The type was invalid 13 | case invalid 14 | 15 | /// The type was a dependent type 16 | case dependent 17 | 18 | /// The type was incomplete 19 | case incomplete 20 | 21 | /// The type did not have a constant size 22 | case notConstantSize 23 | 24 | /// The field specified was not found or invalid 25 | case invalidFieldName 26 | 27 | internal init?(clang: CXTypeLayoutError) { 28 | switch clang { 29 | case CXTypeLayoutError_Dependent: 30 | self = .dependent 31 | case CXTypeLayoutError_Invalid: 32 | self = .invalid 33 | case CXTypeLayoutError_Incomplete: 34 | self = .incomplete 35 | case CXTypeLayoutError_NotConstantSize: 36 | self = .notConstantSize 37 | case CXTypeLayoutError_InvalidFieldName: 38 | self = .invalidFieldName 39 | default: 40 | return nil 41 | } 42 | } 43 | } 44 | 45 | /// Represents a CType that's backed by a CXType directly 46 | protocol ClangTypeBacked: CType { 47 | var clang: CXType { get } 48 | } 49 | 50 | extension ClangTypeBacked { 51 | /// Returns the underlying clang backing store 52 | public func asClang() -> CXType { 53 | return clang 54 | } 55 | } 56 | 57 | extension CXType: CType { 58 | /// Returns self, unmodified 59 | public func asClang() -> CXType { 60 | return self 61 | } 62 | } 63 | 64 | /// Determines if two C types are equal to each other. 65 | public func ==(lhs: CType, rhs: CType) -> Bool { 66 | return clang_equalTypes(lhs.asClang(), rhs.asClang()) != 0 67 | } 68 | 69 | extension CType { 70 | 71 | /// Computes the size of a type in bytes as per C++ [expr.sizeof] standard. 72 | /// - returns: The size of the type in bytes. 73 | /// - throws: 74 | /// - `TypeLayoutError.invalid` if the type declaration is invalid. 75 | /// - `TypeLayoutError.incomplete` if the type declaration is an 76 | /// incomplete type 77 | /// - `TypeLayoutError.dependent` if the type declaration is dependent 78 | public func sizeOf() throws -> Int { 79 | let val = clang_Type_getSizeOf(asClang()) 80 | if let error = TypeLayoutError(clang: CXTypeLayoutError(rawValue: Int32(val))) { 81 | throw error 82 | } 83 | return Int(val) 84 | } 85 | 86 | /// Computes the alignment of a type in bytes as per C++[expr.alignof] 87 | /// standard. 88 | /// - returns: The alignment of the given type, in bytes. 89 | /// - throws: 90 | /// - `TypeLayoutError.invalid` if the type declaration is invalid. 91 | /// - `TypeLayoutError.incomplete` if the type declaration is an 92 | /// incomplete type 93 | /// - `TypeLayoutError.dependent` if the type declaration is dependent 94 | /// - `TypeLayoutError.nonConstantSize` if the type is not a constant 95 | /// size 96 | public func alignOf() throws -> Int { 97 | let val = clang_Type_getAlignOf(asClang()) 98 | if let error = TypeLayoutError(clang: CXTypeLayoutError(rawValue: Int32(val))) { 99 | throw error 100 | } 101 | return Int(val) 102 | } 103 | 104 | /// Pretty-print the underlying type using the rules of the language of the 105 | /// translation unit from which it came. 106 | /// - note: If the type is invalid, an empty string is returned. 107 | public var description: String { 108 | return clang_getTypeSpelling(asClang()).asSwift() 109 | } 110 | 111 | /// Retrieves the cursor for the declaration of the receiver. 112 | public var declaration: Cursor? { 113 | return convertCursor(clang_getTypeDeclaration(asClang())) 114 | } 115 | 116 | /// Retrieves the Objective-C type encoding for the receiver. 117 | public var objcEncoding: String { 118 | return clang_Type_getObjCEncoding(asClang()).asSwift() 119 | } 120 | 121 | /// Return the canonical type for a CType. 122 | /// Clang's type system explicitly models typedefs and all the ways a 123 | /// specific type can be represented. The canonical type is the underlying 124 | /// type with all the "sugar" removed. For example, if 'T' is a typedef for 125 | /// 'int', the canonical type for 'T' would be 'int'. 126 | public var canonicalType: CType { 127 | return convertType(clang_getCanonicalType(asClang()))! 128 | } 129 | 130 | /// Retrieve the ref-qualifier kind of a function or method. 131 | /// The ref-qualifier is returned for C++ functions or methods. For other 132 | /// types or non-C++ declarations, nil is returned. 133 | public var cxxRefQualifier: RefQualifier? { 134 | return RefQualifier(clang: clang_Type_getCXXRefQualifier(asClang())) 135 | } 136 | } 137 | 138 | /// Represents the qualifier for C++ methods that determines how the 139 | /// implicit `this` parameter is used in the method. 140 | public enum RefQualifier { 141 | /// An l-value ref qualifier (&) 142 | case lvalue 143 | 144 | /// An r-value ref qualifier (&&) 145 | case rvalue 146 | 147 | internal init?(clang: CXRefQualifierKind) { 148 | switch clang { 149 | case CXRefQualifier_LValue: self = .lvalue 150 | case CXRefQualifier_RValue: self = .rvalue 151 | default: return nil 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /Sources/Clang/CTypes.swift: -------------------------------------------------------------------------------- 1 | #if SWIFT_PACKAGE 2 | import cclang 3 | #endif 4 | 5 | /// MARK: Special Types 6 | public struct RecordType: ClangTypeBacked { 7 | let clang: CXType 8 | /// Computes the offset of a named field in a record of the given type 9 | /// in bytes as it would be returned by __offsetof__ as per C++11[18.2p4] 10 | /// - returns: The offset of a field with the given name in the type. 11 | /// - throws: 12 | /// - `TypeLayoutError.invalid` if the type declaration is not a record 13 | /// field. 14 | /// - `TypeLayoutError.incomplete` if the type declaration is an 15 | /// incomplete type 16 | /// - `TypeLayoutError.dependent` if the type declaration is dependent 17 | /// - `TypeLayoutError.invalidFieldName` if the field is not found in 18 | /// the receiving type. 19 | public func offsetOf(fieldName: String) throws -> Int { 20 | let val = clang_Type_getOffsetOf(asClang(), fieldName) 21 | if let error = TypeLayoutError(clang: CXTypeLayoutError(rawValue: Int32(val))) { 22 | throw error 23 | } 24 | return Int(val) 25 | } 26 | 27 | /// Gathers and returns all the fields of this record. 28 | public func fields() -> [Cursor] { 29 | let fields = Box([Cursor]()) 30 | let fieldsRef = Unmanaged.passUnretained(fields) 31 | let opaque = fieldsRef.toOpaque() 32 | clang_Type_visitFields(asClang(), { (child, opaque) -> CXVisitorResult in 33 | let fieldsRef = Unmanaged>.fromOpaque(opaque!) 34 | let fields = fieldsRef.takeUnretainedValue() 35 | if let cursor = convertCursor(child) { 36 | fields.value.append(cursor) 37 | } 38 | return CXVisit_Continue 39 | }, opaque) 40 | return fields.value 41 | } 42 | } 43 | 44 | /// MARK: Standard Types 45 | 46 | /// A type whose specific kind is not exposed via this interface. 47 | public struct UnexposedType: ClangTypeBacked { 48 | let clang: CXType 49 | } 50 | 51 | public struct VoidType: ClangTypeBacked { 52 | let clang: CXType 53 | } 54 | 55 | public struct BoolType: ClangTypeBacked { 56 | let clang: CXType 57 | } 58 | 59 | public struct Char_UType: ClangTypeBacked { 60 | let clang: CXType 61 | } 62 | 63 | public struct UCharType: ClangTypeBacked { 64 | let clang: CXType 65 | } 66 | 67 | public struct Char16Type: ClangTypeBacked { 68 | let clang: CXType 69 | } 70 | 71 | public struct Char32Type: ClangTypeBacked { 72 | let clang: CXType 73 | } 74 | 75 | public struct UShortType: ClangTypeBacked { 76 | let clang: CXType 77 | } 78 | 79 | public struct UIntType: ClangTypeBacked { 80 | let clang: CXType 81 | } 82 | 83 | public struct ULongType: ClangTypeBacked { 84 | let clang: CXType 85 | } 86 | 87 | public struct ULongLongType: ClangTypeBacked { 88 | let clang: CXType 89 | } 90 | 91 | public struct UInt128Type: ClangTypeBacked { 92 | let clang: CXType 93 | } 94 | 95 | public struct Char_SType: ClangTypeBacked { 96 | let clang: CXType 97 | } 98 | 99 | public struct SCharType: ClangTypeBacked { 100 | let clang: CXType 101 | } 102 | 103 | public struct WCharType: ClangTypeBacked { 104 | let clang: CXType 105 | } 106 | 107 | public struct ShortType: ClangTypeBacked { 108 | let clang: CXType 109 | } 110 | 111 | public struct IntType: ClangTypeBacked { 112 | let clang: CXType 113 | } 114 | 115 | public struct LongType: ClangTypeBacked { 116 | let clang: CXType 117 | } 118 | 119 | public struct LongLongType: ClangTypeBacked { 120 | let clang: CXType 121 | } 122 | 123 | public struct Int128Type: ClangTypeBacked { 124 | let clang: CXType 125 | } 126 | 127 | public struct FloatType: ClangTypeBacked { 128 | let clang: CXType 129 | } 130 | 131 | public struct DoubleType: ClangTypeBacked { 132 | let clang: CXType 133 | } 134 | 135 | public struct LongDoubleType: ClangTypeBacked { 136 | let clang: CXType 137 | } 138 | 139 | public struct NullPtrType: ClangTypeBacked { 140 | let clang: CXType 141 | } 142 | 143 | public struct OverloadType: ClangTypeBacked { 144 | let clang: CXType 145 | } 146 | 147 | public struct DependentType: ClangTypeBacked { 148 | let clang: CXType 149 | } 150 | 151 | public struct ObjCIdType: ClangTypeBacked { 152 | let clang: CXType 153 | } 154 | 155 | public struct ObjCClassType: ClangTypeBacked { 156 | let clang: CXType 157 | } 158 | 159 | public struct ObjCSelType: ClangTypeBacked { 160 | let clang: CXType 161 | } 162 | 163 | public struct Float128Type: ClangTypeBacked { 164 | let clang: CXType 165 | } 166 | 167 | public struct ComplexType: ClangTypeBacked { 168 | let clang: CXType 169 | } 170 | 171 | public struct PointerType: ClangTypeBacked { 172 | let clang: CXType 173 | 174 | public var pointee: CType? { 175 | return convertType(clang_getPointeeType(clang)) 176 | } 177 | } 178 | 179 | public struct BlockPointerType: ClangTypeBacked { 180 | let clang: CXType 181 | } 182 | 183 | public struct LValueReferenceType: ClangTypeBacked { 184 | let clang: CXType 185 | } 186 | 187 | public struct RValueReferenceType: ClangTypeBacked { 188 | let clang: CXType 189 | } 190 | 191 | public struct EnumType: ClangTypeBacked { 192 | let clang: CXType 193 | } 194 | 195 | public struct TypedefType: ClangTypeBacked { 196 | let clang: CXType 197 | } 198 | 199 | public struct ObjCInterfaceType: ClangTypeBacked { 200 | let clang: CXType 201 | } 202 | 203 | public struct ObjCTypeParam: ClangTypeBacked { 204 | let clang: CXType 205 | } 206 | 207 | public struct ObjCObjectPointerType: ClangTypeBacked { 208 | let clang: CXType 209 | } 210 | 211 | public struct FunctionNoProtoType: ClangTypeBacked { 212 | let clang: CXType 213 | } 214 | 215 | public struct FunctionProtoType: ClangTypeBacked { 216 | let clang: CXType 217 | } 218 | 219 | public struct ConstantArrayType: ClangTypeBacked { 220 | let clang: CXType 221 | 222 | public var element: CType? { 223 | return convertType(clang_getArrayElementType(clang)) 224 | } 225 | 226 | public var count: Int32 { 227 | return clang_getNumArgTypes(clang) 228 | } 229 | } 230 | 231 | public struct VectorType: ClangTypeBacked { 232 | let clang: CXType 233 | } 234 | 235 | public struct IncompleteArrayType: ClangTypeBacked { 236 | let clang: CXType 237 | 238 | public var element: CType? { 239 | return convertType(clang_getArrayElementType(clang)) 240 | } 241 | } 242 | 243 | public struct VariableArrayType: ClangTypeBacked { 244 | let clang: CXType 245 | 246 | public var element: CType? { 247 | return convertType(clang_getArrayElementType(clang)) 248 | } 249 | } 250 | 251 | public struct DependentSizedArrayType: ClangTypeBacked { 252 | let clang: CXType 253 | } 254 | 255 | public struct MemberPointerType: ClangTypeBacked { 256 | let clang: CXType 257 | } 258 | 259 | public struct AutoType: ClangTypeBacked { 260 | let clang: CXType 261 | } 262 | 263 | /// Represents a type that was referred to using an elaborated type keyword. 264 | public struct ElaboratedType: ClangTypeBacked { 265 | let clang: CXType 266 | } 267 | 268 | /// Converts a CXType to a CType, returning `nil` if it was unsuccessful 269 | func convertType(_ clang: CXType) -> CType? { 270 | switch clang.kind { 271 | case CXType_Invalid: return nil 272 | case CXType_Unexposed: return UnexposedType(clang: clang) 273 | case CXType_Void: return VoidType(clang: clang) 274 | case CXType_Bool: return BoolType(clang: clang) 275 | case CXType_Char_U: return Char_UType(clang: clang) 276 | case CXType_UChar: return UCharType(clang: clang) 277 | case CXType_Char16: return Char16Type(clang: clang) 278 | case CXType_Char32: return Char32Type(clang: clang) 279 | case CXType_UShort: return UShortType(clang: clang) 280 | case CXType_UInt: return UIntType(clang: clang) 281 | case CXType_ULong: return ULongType(clang: clang) 282 | case CXType_ULongLong: return ULongLongType(clang: clang) 283 | case CXType_UInt128: return UInt128Type(clang: clang) 284 | case CXType_Char_S: return Char_SType(clang: clang) 285 | case CXType_SChar: return SCharType(clang: clang) 286 | case CXType_WChar: return WCharType(clang: clang) 287 | case CXType_Short: return ShortType(clang: clang) 288 | case CXType_Int: return IntType(clang: clang) 289 | case CXType_Long: return LongType(clang: clang) 290 | case CXType_LongLong: return LongLongType(clang: clang) 291 | case CXType_Int128: return Int128Type(clang: clang) 292 | case CXType_Float: return FloatType(clang: clang) 293 | case CXType_Double: return DoubleType(clang: clang) 294 | case CXType_LongDouble: return LongDoubleType(clang: clang) 295 | case CXType_NullPtr: return NullPtrType(clang: clang) 296 | case CXType_Overload: return OverloadType(clang: clang) 297 | case CXType_Dependent: return DependentType(clang: clang) 298 | case CXType_ObjCId: return ObjCIdType(clang: clang) 299 | case CXType_ObjCClass: return ObjCClassType(clang: clang) 300 | case CXType_ObjCSel: return ObjCSelType(clang: clang) 301 | case CXType_Float128: return Float128Type(clang: clang) 302 | case CXType_Complex: return ComplexType(clang: clang) 303 | case CXType_Pointer: return PointerType(clang: clang) 304 | case CXType_BlockPointer: return BlockPointerType(clang: clang) 305 | case CXType_LValueReference: return LValueReferenceType(clang: clang) 306 | case CXType_RValueReference: return RValueReferenceType(clang: clang) 307 | case CXType_Record: return RecordType(clang: clang) 308 | case CXType_Enum: return EnumType(clang: clang) 309 | case CXType_Typedef: return TypedefType(clang: clang) 310 | case CXType_ObjCInterface: return ObjCInterfaceType(clang: clang) 311 | case CXType_ObjCObjectPointer: return ObjCObjectPointerType(clang: clang) 312 | case CXType_ObjCTypeParam: return ObjCTypeParam(clang: clang) 313 | case CXType_FunctionNoProto: return FunctionNoProtoType(clang: clang) 314 | case CXType_FunctionProto: return FunctionProtoType(clang: clang) 315 | case CXType_ConstantArray: return ConstantArrayType(clang: clang) 316 | case CXType_Vector: return VectorType(clang: clang) 317 | case CXType_IncompleteArray: return IncompleteArrayType(clang: clang) 318 | case CXType_VariableArray: return VariableArrayType(clang: clang) 319 | case CXType_DependentSizedArray: return DependentSizedArrayType(clang: clang) 320 | case CXType_MemberPointer: return MemberPointerType(clang: clang) 321 | case CXType_Auto: return AutoType(clang: clang) 322 | case CXType_Elaborated: return ElaboratedType(clang: clang) 323 | default: fatalError("invalid CXTypeKind \(clang)") 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /Sources/Clang/ClangError.swift: -------------------------------------------------------------------------------- 1 | #if SWIFT_PACKAGE 2 | import cclang 3 | #endif 4 | 5 | /// Represents the errors that can be thrown by libclang. 6 | public enum ClangError: Error { 7 | /// Clang had an internal failure while processing the request. 8 | case failure 9 | 10 | /// Clang crashed while processing the request. 11 | case crashed 12 | 13 | /// The arguments provided to the clang invocation were invalid. 14 | case invalidArguments 15 | 16 | /// Clang failed to parse an AST from the provided source file(s). 17 | case astRead 18 | 19 | /// Constructs a ClangError from the provided CXErrorCode 20 | init?(clang: CXErrorCode) { 21 | switch clang { 22 | case CXError_Failure: self = .failure 23 | case CXError_Crashed: self = .crashed 24 | case CXError_ASTReadError: self = .astRead 25 | case CXError_InvalidArguments: self = .invalidArguments 26 | default: return nil 27 | } 28 | } 29 | } 30 | 31 | /// Represents the errors that can be thrown by libclang when saving a 32 | /// `TranslationUnit`. 33 | public enum ClangSaveError: Error { 34 | /// Indicates that an unknown error occurred while attempting to save the 35 | /// file. 36 | /// This error typically indicates that file I/O failed when attempting to 37 | /// write the file. 38 | case unknown 39 | 40 | /// Indicates that errors during translation prevented this attempt to save 41 | /// the translation unit. 42 | /// Errors that prevent the translation unit from being saved can be extracted 43 | /// using diagnostics. 44 | case translationErrors 45 | 46 | /// Indicates that the translation unit to be saved was somehow invalid. 47 | case invalidTranslationUnit 48 | 49 | /// Constructs a ClangSaveError from the provided CXSaveError. 50 | init?(clang: CXSaveError) { 51 | switch clang { 52 | case CXSaveError_Unknown: self = .unknown 53 | case CXSaveError_TranslationErrors: self = .translationErrors 54 | case CXSaveError_InvalidTU: self = .invalidTranslationUnit 55 | default: return nil 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Sources/Clang/Comment.swift: -------------------------------------------------------------------------------- 1 | #if SWIFT_PACKAGE 2 | import cclang 3 | #endif 4 | 5 | /// A `Comment` is a parsed documentation comment in a C/C++/Objective-C source 6 | /// file. 7 | public protocol Comment { 8 | var clang: CXComment { get } 9 | } 10 | 11 | extension Comment { 12 | /// Retreives all children of this comment. 13 | public var children: AnyRandomAccessCollection { 14 | let count = clang_Comment_getNumChildren(clang) 15 | return AnyRandomAccessCollection(count: Int(count), indexingOperation: child) 16 | } 17 | 18 | /// - parameter index: The index of the child you're getting. 19 | /// - returns: The specified child of the AST node. 20 | public func child(at index: Int) -> Comment? { 21 | return convertComment(clang_Comment_getChild(clang, UInt32(index))) 22 | } 23 | 24 | /// The first child of this comment, if there are any children. 25 | public var firstChild: Comment? { 26 | let count = clang_Comment_getNumChildren(clang) 27 | if count == 0 { return nil } 28 | return convertComment(clang_Comment_getChild(clang, 0)) 29 | } 30 | } 31 | 32 | public struct FullComment: Comment { 33 | public let clang: CXComment 34 | 35 | /// Convert a given full parsed comment to an HTML fragment. 36 | /// Specific details of HTML layout are subject to change. Don't try to parse 37 | /// this HTML back into an AST, use other APIs instead. 38 | /// Currently the following CSS classes are used: 39 | /// - `para-brief` for \brief paragraph and equivalent commands 40 | /// - `para-returns` for \returns paragraph and equivalent commands 41 | /// - `word-returns` for the `Returns` word in \returns paragraph. 42 | /// Function argument documentation is rendered as a
list with arguments 43 | /// sorted in function prototype order. CSS classes used: 44 | /// - `param-name-index-NUMBER` for parameter name (
) 45 | /// - `param-descr-index-NUMBER` for parameter description (
) 46 | /// - `param-name-index-invalid` and `param-descr-index-invalid` are used if 47 | /// parameter index is invalid. 48 | /// Template parameter documentation is rendered as a
list with 49 | /// parameters sorted in template parameter list order. CSS classes used: 50 | /// - `tparam-name-index-NUMBER` for parameter name (
) 51 | /// - `tparam-descr-index-NUMBER` for parameter description (
) 52 | /// - `tparam-name-index-other` and `tparam-descr-index-other` are used for 53 | /// names inside template template parameters 54 | /// - `tparam-name-index-invalid` and `tparam-descr-index-invalid` are used if 55 | /// parameter position is invalid. 56 | public var html: String { 57 | return clang_FullComment_getAsHTML(clang).asSwift() 58 | } 59 | 60 | /// Convert a given full parsed comment to an XML document. 61 | /// A Relax NG schema for the XML can be found in comment-xml-schema.rng file 62 | /// inside the clang source tree. 63 | public var xml: String { 64 | return clang_FullComment_getAsXML(clang).asSwift() 65 | } 66 | } 67 | 68 | /// A plain text comment. 69 | public struct TextComment: Comment { 70 | public let clang: CXComment 71 | 72 | /// Retrieves the text contained in the AST node. 73 | public var text: String { 74 | return clang_TextComment_getText(clang).asSwift() 75 | } 76 | } 77 | 78 | /// A command with word-like arguments that is considered inline content. 79 | /// For example: `\c command` 80 | public struct InlineCommandComment: Comment { 81 | public let clang: CXComment 82 | 83 | /// Retrieves all arguments of this inline command. 84 | public var arguments: AnyRandomAccessCollection { 85 | let count = clang_InlineCommandComment_getNumArgs(clang) 86 | return AnyRandomAccessCollection(count: count) { index in 87 | return clang_InlineCommandComment_getArgText(self.clang, index).asSwift() 88 | } 89 | } 90 | } 91 | 92 | /// Describes the attributes in an HTML tag, for example: 93 | /// ``` 94 | /// 95 | /// ``` 96 | /// Would have 1 attribute, with a name `"href"`, and value 97 | /// `"https://example.org"` 98 | public struct HTMLAttribute { 99 | /// The name of the attribute, which comes before the `=`. 100 | public let name: String 101 | 102 | /// The value in the attribute, which comes after the `=`. 103 | public let value: String 104 | } 105 | 106 | /// An HTML start tag with attributes (name-value pairs). Considered inline 107 | /// content. 108 | /// For example: 109 | /// ``` 110 | /// 111 | /// ``` 112 | public struct HTMLStartTagComment: Comment { 113 | public let clang: CXComment 114 | 115 | /// Retrieves all attributes of this HTML start tag. 116 | public var attributes: AnyRandomAccessCollection { 117 | let count = clang_HTMLStartTag_getNumAttrs(clang) 118 | return AnyRandomAccessCollection(count: count) { index in 119 | let name = clang_HTMLStartTag_getAttrName(self.clang, index).asSwift() 120 | let value = clang_HTMLStartTag_getAttrValue(self.clang, index).asSwift() 121 | return HTMLAttribute(name: name, value: value) 122 | } 123 | } 124 | } 125 | 126 | /// An HTML end tag. Considered inline content. 127 | /// For example: 128 | /// ``` 129 | /// 130 | /// ``` 131 | public struct HTMLEndTagComment: Comment { 132 | public let clang: CXComment 133 | } 134 | 135 | /// A paragraph, contains inline comment. The paragraph itself is block content. 136 | public struct ParagraphComment: Comment { 137 | public let clang: CXComment 138 | } 139 | 140 | /// A command that has zero or more word-like arguments (number of word-like 141 | /// arguments depends on command name) and a paragraph as an argument. Block 142 | /// command is block content. 143 | /// Paragraph argument is also a child of the block command. 144 | /// For example: `\brief` has 0 word-like arguments and a paragraph argument. 145 | /// AST nodes of special kinds that parser knows about (e. g., the `\param` 146 | /// command) have their own node kinds. 147 | public struct BlockCommandComment: Comment { 148 | public let clang: CXComment 149 | 150 | /// Retrieves the name of this block command. 151 | public var name: String { 152 | return clang_BlockCommandComment_getCommandName(clang).asSwift() 153 | } 154 | 155 | /// Retrieves all attributes of this HTML start tag. 156 | public var arguments: AnyRandomAccessCollection { 157 | let count = clang_BlockCommandComment_getNumArgs(clang) 158 | return AnyRandomAccessCollection(count: count) { index in 159 | return clang_BlockCommandComment_getArgText(self.clang, index).asSwift() 160 | } 161 | } 162 | 163 | /// Retrieves the paragraph argument of the block command. 164 | public var paragraph: ParagraphComment { 165 | return ParagraphComment(clang: clang_BlockCommandComment_getParagraph(clang)) 166 | } 167 | } 168 | 169 | /// Describes parameter passing direction for \param or \arg command. 170 | /// This determines how the callee of a function intends to use the argument. 171 | /// For example, an `.in` argument is meant to be consumed or read by the 172 | /// caller. An `.out` argument is usually a pointer and is meant to be filled 173 | /// by the caller, usually to return multiple pieces of data from a function. 174 | /// An `.inout` argument is meant to be read and written out to by the caller. 175 | public enum ParamPassDirection { 176 | /// The parameter is an input parameter. 177 | case `in` 178 | 179 | /// The parameter is an output parameter. 180 | case out 181 | 182 | /// The parameter is an input and output parameter. 183 | case `inout` 184 | 185 | init(clang: CXCommentParamPassDirection) { 186 | switch clang { 187 | case CXCommentParamPassDirection_In: self = .in 188 | case CXCommentParamPassDirection_Out: self = .out 189 | case CXCommentParamPassDirection_InOut: self = .inout 190 | default: fatalError("invalud CXCommentParamPassDirection: \(clang)") 191 | } 192 | } 193 | } 194 | 195 | /// A \param or \arg command that describes the function parameter (name, 196 | /// passing direction, description). 197 | /// For example: 198 | /// ``` 199 | /// \param [in] ParamName description. 200 | /// ``` 201 | public struct ParamCommandComment: Comment { 202 | public let clang: CXComment 203 | 204 | /// Retrieves the zero-based parameter index in the function prototype. 205 | public var index: Int { 206 | return Int(clang_ParamCommandComment_getParamIndex(clang)) 207 | } 208 | 209 | /// The direction this parameter is passed by. 210 | public var passDirection: ParamPassDirection { 211 | return ParamPassDirection(clang: clang_ParamCommandComment_getDirection(clang)) 212 | } 213 | 214 | /// Retrieves the name of the declared parameter. 215 | public var name: String { 216 | return clang_ParamCommandComment_getParamName(clang).asSwift() 217 | } 218 | 219 | /// Determine if this parameter is actually a valid parameter in the declared 220 | /// function 221 | public var isValidIndex: Bool { 222 | return clang_ParamCommandComment_isParamIndexValid(clang) != 0 223 | } 224 | 225 | /// Determines if the parameter's direction was explicitly stated in the 226 | /// function prototype. 227 | public var isExplicitDirection: Bool { 228 | return clang_ParamCommandComment_isDirectionExplicit(clang) != 0 229 | } 230 | } 231 | 232 | /// A \tparam command that describes a template parameter (name and description). 233 | /// For example: 234 | /// ``` 235 | /// \tparam T description. 236 | /// ``` 237 | public struct TParamCommandComment: Comment { 238 | public let clang: CXComment 239 | 240 | /// Determines the zero-based nesting depth of this parameter in the template 241 | /// parameter list. 242 | /// For example, 243 | /// ``` 244 | /// template class TT> 245 | /// void test(TT aaa); 246 | /// ``` 247 | /// for `C` and `TT` the nesting depth is 0, and for `T` the nesting 248 | /// depth is `1`. 249 | public var depth: Int { 250 | return Int(clang_TParamCommandComment_getDepth(clang)) 251 | } 252 | } 253 | 254 | /// A verbatim block command (e. g., preformatted code). Verbatim block has an 255 | /// opening and a closing command and contains multiple lines of text 256 | /// (VerbatimBlockLine child nodes). 257 | /// For example: 258 | /// ``` 259 | /// \verbatim 260 | /// aaa 261 | /// \endverbatim 262 | /// ``` 263 | public struct VerbatimBlockCommandComment: Comment { 264 | public let clang: CXComment 265 | 266 | /// Retrieves the name of this block command. 267 | public var name: String { 268 | return clang_BlockCommandComment_getCommandName(clang).asSwift() 269 | } 270 | 271 | /// Retrieves all attributes of this HTML start tag. 272 | public var arguments: AnyRandomAccessCollection { 273 | let count = clang_BlockCommandComment_getNumArgs(clang) 274 | return AnyRandomAccessCollection(count: count) { index in 275 | return clang_BlockCommandComment_getArgText(self.clang, index).asSwift() 276 | } 277 | } 278 | 279 | /// Retrieves the paragraph argument of the block command. 280 | public var paragraph: ParagraphComment { 281 | return ParagraphComment(clang: clang_BlockCommandComment_getParagraph(clang)) 282 | } 283 | } 284 | 285 | /// A line of text that is contained within a `VerbatimBlockCommand` 286 | /// node. 287 | public struct VerbatimBlockLineComment: Comment { 288 | public let clang: CXComment 289 | 290 | /// The text of this comment. 291 | public var text: String { 292 | return clang_VerbatimBlockLineComment_getText(clang).asSwift() 293 | } 294 | } 295 | 296 | /// A verbatim line command. Verbatim line has an opening command, a single 297 | /// line of text (up to the newline after the opening command) and has no 298 | /// closing command. 299 | public struct VerbatimLineComment: Comment { 300 | public let clang: CXComment 301 | 302 | /// The text of this comment. 303 | public var text: String { 304 | return clang_VerbatimLineComment_getText(clang).asSwift() 305 | } 306 | } 307 | 308 | /// Converts a `CXComment` into a `Comment`. 309 | internal func convertComment(_ clang: CXComment) -> Comment? { 310 | switch clang_Comment_getKind(clang) { 311 | case CXComment_Null: return nil 312 | case CXComment_Text: return TextComment(clang: clang) 313 | case CXComment_InlineCommand: return InlineCommandComment(clang: clang) 314 | case CXComment_HTMLStartTag: return HTMLStartTagComment(clang: clang) 315 | case CXComment_HTMLEndTag: return HTMLEndTagComment(clang: clang) 316 | case CXComment_Paragraph: return ParagraphComment(clang: clang) 317 | case CXComment_BlockCommand: return BlockCommandComment(clang: clang) 318 | case CXComment_ParamCommand: return ParamCommandComment(clang: clang) 319 | case CXComment_TParamCommand: return TParamCommandComment(clang: clang) 320 | case CXComment_VerbatimBlockCommand: return VerbatimBlockCommandComment(clang: clang) 321 | case CXComment_VerbatimBlockLine: return VerbatimBlockLineComment(clang: clang) 322 | case CXComment_VerbatimLine: return VerbatimLineComment(clang: clang) 323 | case CXComment_FullComment: return FullComment(clang: clang) 324 | default: fatalError("invalid kind \(clang)") 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /Sources/Clang/Cursor.swift: -------------------------------------------------------------------------------- 1 | #if SWIFT_PACKAGE 2 | import cclang 3 | #endif 4 | 5 | /// A cursor representing some element in the abstract syntax tree for a 6 | /// translation unit. 7 | /// 8 | /// The cursor abstraction unifies the different kinds of entities in a 9 | /// program--declaration, statements, expressions, references to declarations, 10 | /// etc.--under a single "cursor" abstraction with a common set of operations. 11 | /// Common operation for a cursor include: getting the physical location in a 12 | /// source file where the cursor points, getting the name associated with a 13 | /// cursor, and retrieving cursors for any child nodes of a particular cursor. 14 | /// Cursors can be produced in two specific ways. 15 | /// 16 | /// `TranslationUnit.cursor` 17 | /// produces a cursor for a translation unit, from which one can use 18 | /// `children() to explore the rest of the translation unit. 19 | /// 20 | /// `SourceLocation.cursor` maps from a physical source location to the entity 21 | /// that resides at that location, allowing one to map from the source code into 22 | /// the AST. 23 | public protocol Cursor: CustomStringConvertible { 24 | /// Converts this cursor value to a CXCursor value to be consumed by 25 | /// libclang APIs 26 | func asClang() -> CXCursor 27 | } 28 | 29 | /// Used as the return type for `Cursor.visitChildren`. Describes what to do 30 | /// after each iteration of a child visitation. 31 | public enum ChildVisitResult { 32 | /// Stop visitation. 33 | case abort 34 | 35 | /// Recurse into this cursor (if it has children). 36 | case recurse 37 | 38 | /// Continue to the next sibling without visiting this cursor's children. 39 | case `continue` 40 | } 41 | 42 | /// Represents a cursor type that is simply backed by a CXCursor 43 | internal protocol ClangCursorBacked: Cursor { 44 | var clang: CXCursor { get } 45 | } 46 | 47 | extension ClangCursorBacked { 48 | /// Returns the underlying CXCursor value 49 | public func asClang() -> CXCursor { 50 | return clang 51 | } 52 | } 53 | 54 | extension CXCursor: Cursor { 55 | /// Returns `self` unmodified. 56 | public func asClang() -> CXCursor { 57 | return self 58 | } 59 | } 60 | 61 | /// Compares two `Cursor`s and determines if they are equivalent. 62 | public func ==(lhs: Cursor, rhs: Cursor) -> Bool { 63 | return clang_equalCursors(lhs.asClang(), rhs.asClang()) != 0 64 | } 65 | 66 | extension Cursor { 67 | 68 | /// Retrieve a name for the entity referenced by this cursor. 69 | public var description: String { 70 | return clang_getCursorSpelling(asClang()).asSwift() 71 | } 72 | 73 | /// Retrieve a Unified Symbol Resolution (USR) for the entity referenced by 74 | /// the given cursor. 75 | /// A Unified Symbol Resolution (USR) is a string that identifies a 76 | /// particular entity (function, class, variable, etc.) within a program. 77 | /// USRs can be compared across translation units to determine, e.g., when 78 | /// references in one translation refer to an entity defined in another 79 | /// translation unit. 80 | public var usr: String { 81 | return clang_getCursorUSR(asClang()).asSwift() 82 | } 83 | 84 | /// For a cursor that is either a reference to or a declaration of some 85 | /// entity, retrieve a cursor that describes the definition of that entity. 86 | /// Some entities can be declared multiple times within a translation unit, 87 | /// but only one of those declarations can also be a definition. For 88 | /// example, given: 89 | /// ``` 90 | /// int f(int, int); 91 | /// int g(int x, int y) { return f(x, y); } 92 | /// int f(int a, int b) { return a + b; } 93 | /// int f(int, int); 94 | /// ``` 95 | /// there are three declarations of the function "f", but only the second 96 | /// one is a definition. This variable, accessed on any cursor pointing to a 97 | /// declaration of "f" (the first or fourth lines of the example) or a 98 | /// cursor referenced that uses "f" (the call to "f' inside "g"), will 99 | /// return a declaration cursor pointing to the definition (the second "f" 100 | /// declaration). 101 | /// 102 | /// If given a cursor for which there is no corresponding definition, e.g., 103 | /// because there is no definition of that entity within this translation 104 | /// unit, returns a `NULL` cursor. 105 | public var definition: Cursor? { 106 | return convertCursor(clang_getCursorDefinition(asClang())) 107 | } 108 | 109 | /// Retrieve the display name for the entity referenced by this cursor. 110 | /// The display name contains extra information that helps identify the 111 | /// cursor, such as the parameters of a function or template or the 112 | /// arguments of a class template specialization. 113 | public var displayName: String { 114 | return clang_getCursorDisplayName(asClang()).asSwift() 115 | } 116 | 117 | /// Determine the lexical parent of the given cursor. 118 | /// The lexical parent of a cursor is the cursor in which the given cursor 119 | /// was actually written. For many declarations, the lexical and semantic 120 | /// parents are equivalent. They diverge when declarations or definitions 121 | /// are provided out-of-line. For example: 122 | /// 123 | /// ``` 124 | /// class C { 125 | /// void f(); 126 | /// }; 127 | /// void C::f() { } 128 | /// ``` 129 | /// 130 | /// In the out-of-line definition of `C::f`, the semantic parent is the class 131 | /// `C`, of which this function is a member. The lexical parent is the place 132 | /// where the declaration actually occurs in the source code; in this case, 133 | /// the definition occurs in the translation unit. In general, the lexical 134 | /// parent for a given entity can change without affecting the semantics of 135 | /// the program, and the lexical parent of different declarations of the 136 | /// same entity may be different. Changing the semantic parent of a 137 | /// declaration, on the other hand, can have a major impact on semantics, 138 | /// and redeclarations of a particular entity should all have the same 139 | /// semantic context. 140 | /// 141 | /// In the example above, both declarations of `C::f` have `C` as their 142 | /// semantic context, while the lexical context of the first `C::f` is `C` 143 | /// and the lexical context of the second `C::f` is the translation unit. 144 | /// For global declarations, the semantic parent is the translation unit. 145 | public var lexicalParent: Cursor? { 146 | return convertCursor(clang_getCursorLexicalParent(asClang())) 147 | } 148 | 149 | /// Determine the semantic parent of the given cursor. 150 | /// The semantic parent of a cursor is the cursor that semantically contains 151 | /// the given cursor. For many declarations, the lexical and semantic 152 | /// parents are equivalent. They diverge when declarations or definitions 153 | /// are provided out-of-line. For example: 154 | /// 155 | /// ``` 156 | /// class C { 157 | /// void f(); 158 | /// }; 159 | /// void C::f() { } 160 | /// ``` 161 | /// 162 | /// In the out-of-line definition of `C::f`, the semantic parent is the class 163 | /// `C`, of which this function is a member. The lexical parent is the place 164 | /// where the declaration actually occurs in the source code; in this case, 165 | /// the definition occurs in the translation unit. In general, the lexical 166 | /// parent for a given entity can change without affecting the semantics of 167 | /// the program, and the lexical parent of different declarations of the 168 | /// same entity may be different. Changing the semantic parent of a 169 | /// declaration, on the other hand, can have a major impact on semantics, 170 | /// and redeclarations of a particular entity should all have the same 171 | /// semantic context. 172 | /// 173 | /// In the example above, both declarations of `C::f` have `C` as their 174 | /// semantic context, while the lexical context of the first `C::f` is `C` 175 | /// and the lexical context of the second `C::f` is the translation unit. 176 | /// For global declarations, the semantic parent is the translation unit. 177 | public var semanticParent: Cursor? { 178 | return convertCursor(clang_getCursorSemanticParent(asClang())) 179 | } 180 | 181 | /// For a cursor that is a reference, retrieve a cursor representing the 182 | /// entity that it references. 183 | /// Reference cursors refer to other entities in the AST. For example, an 184 | /// Objective-C superclass reference cursor refers to an Objective-C class. 185 | /// This function produces the cursor for the Objective-C class from the 186 | /// cursor for the superclass reference. If the input cursor is a 187 | /// declaration or definition, it returns that declaration or definition 188 | /// unchanged. Otherwise, returns the `NULL` cursor. 189 | public var referenced: Cursor? { 190 | return convertCursor(clang_getCursorReferenced(asClang())) 191 | } 192 | 193 | /// Retrieves the type of this cursor (if any). 194 | public var type: CType? { 195 | return convertType(clang_getCursorType(asClang())) 196 | } 197 | 198 | /// Returns the translation unit that a cursor originated from. 199 | public var translationUnit: TranslationUnit { 200 | return TranslationUnit(clang: clang_Cursor_getTranslationUnit(asClang()), owned: false) 201 | } 202 | 203 | /// Retrieves all the children of the provided cursor. 204 | /// 205 | /// - returns: An array of `Cursors` that are children of this cursor. 206 | public func children() -> [Cursor] { 207 | var children = [Cursor]() 208 | clang_visitChildrenWithBlock(asClang()) { child, _ in 209 | if let cursor = convertCursor(child) { 210 | children.append(cursor) 211 | } 212 | return CXChildVisit_Continue 213 | } 214 | return children 215 | } 216 | 217 | /// Describe the visibility of the entity referred to by a cursor. 218 | /// This returns the default visibility if not explicitly specified by a 219 | /// visibility attribute. The default visibility may be changed by 220 | /// commandline arguments. 221 | public var visiblity: VisibilityKind? { 222 | return VisibilityKind(clang: clang_getCursorVisibility(asClang())) 223 | } 224 | 225 | /// Retrieve the physical extent of the source construct referenced by the 226 | /// given cursor. 227 | /// The extent of a cursor starts with the file/line/column pointing at the 228 | /// first character within the source construct that the cursor refers to 229 | /// and ends with the last character within that source construct. For a 230 | /// declaration, the extent covers the declaration itself. For a reference, 231 | /// the extent covers the location of the reference (e.g., where the 232 | /// referenced entity was actually used). 233 | public var range: SourceRange { 234 | return SourceRange(clang: clang_getCursorExtent(asClang())) 235 | } 236 | 237 | /// Describes any availability information that specifies if the declaration 238 | /// in question is deprecated or marked unavailable, and on which platforms 239 | /// and versions this availability declaration applies. 240 | public var availability: Availability { 241 | let maxNumPlatforms = 10 // 10 ought to be enough for anybody... 242 | let platformAvailabilities = 243 | UnsafeMutablePointer.allocate(capacity: maxNumPlatforms) 244 | var alwaysDeprecated: Int32 = 0 245 | var deprecatedMessage = CXString() 246 | var alwaysUnavailable: Int32 = 0 247 | var unavailableMessage = CXString() 248 | let numPlatforms = clang_getCursorPlatformAvailability(asClang(), 249 | &alwaysDeprecated, 250 | &deprecatedMessage, 251 | &alwaysUnavailable, 252 | &unavailableMessage, 253 | platformAvailabilities, 254 | Int32(maxNumPlatforms)) 255 | 256 | var platforms = [PlatformAvailability]() 257 | for i in 0.. EvalResult? { 372 | guard let result = clang_Cursor_Evaluate(asClang()) else { return nil } 373 | return convertEvalResult(result) 374 | } 375 | 376 | /// Visits each of the children of this cursor, calling the provided 377 | /// callback for each child. 378 | /// - parameter perCursorCallback: The callback to call with each child in 379 | /// the receiver. 380 | /// - note: The returned value of this callback defines what the next item 381 | /// visited will be. See `ChildVisitResult` for a list of possible 382 | /// results. 383 | public func visitChildren(_ perCursorCallback: (Cursor) -> ChildVisitResult) { 384 | withoutActuallyEscaping(perCursorCallback) { callback -> Void in 385 | clang_visitChildrenWithBlock(asClang()) { 386 | (thisCursor, parentCursor) -> CXChildVisitResult in 387 | guard let cursor = convertCursor(thisCursor) else { 388 | return CXChildVisit_Continue 389 | } 390 | 391 | let result = callback(cursor) 392 | switch result { 393 | case .abort: return CXChildVisit_Break 394 | case .recurse: return CXChildVisit_Recurse 395 | case .continue: return CXChildVisit_Continue 396 | } 397 | } 398 | } 399 | } 400 | 401 | /// Retrieve the nil cursor, which represents no entity. 402 | public static var null: Cursor { 403 | return clang_getNullCursor() 404 | } 405 | } 406 | 407 | /// Describes the visibility of a given symbol at link time. 408 | public enum VisibilityKind { 409 | /// Symbol not seen by the linker. 410 | case hidden 411 | /// Symbol seen by the linker but resolves to a symbol inside this object. 412 | case protected 413 | /// Symbol seen by the linker and acts like a normal symbol. 414 | case `default` 415 | 416 | internal init?(clang: CXVisibilityKind) { 417 | switch clang { 418 | case CXVisibility_Hidden: self = .hidden 419 | case CXVisibility_Protected: self = .protected 420 | case CXVisibility_Default: self = .default 421 | default: return nil 422 | } 423 | } 424 | } 425 | 426 | /// Describes the kind of a template argument. 427 | public enum TemplateArgumentKind { 428 | /// Represents an empty template argument, e.g., one that has not been 429 | /// deduced. 430 | case null 431 | 432 | /// The template argument is a type, i.e. `std::vector` 433 | case type 434 | 435 | /// The template argument is a declaration that was provided for a pointer, 436 | /// reference, or pointer to member non-type template parameter. 437 | case declaration 438 | 439 | /// The template argument is a null pointer or null pointer to member that 440 | /// was provided for a non-type template parameter. 441 | case nullPtr 442 | 443 | /// The template argument is an integral value that was provided for an 444 | /// integral non-type template parameter. 445 | case integral 446 | 447 | /// The template argument is a template name that was provided for a 448 | /// `template