├── .gitignore ├── README.txt ├── SourceCodeKit.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── SourceCodeKit ├── SCKClangSourceFile.h ├── SCKClangSourceFile.m ├── SCKCodeCompletionResult.h ├── SCKCodeCompletionResult.m ├── SCKIntrospection.h ├── SCKIntrospection.m ├── SCKProject.h ├── SCKProject.m ├── SCKSourceCollection.h ├── SCKSourceCollection.m ├── SCKSourceFile.h ├── SCKSourceFile.m ├── SCKSyntaxHighlighter.h ├── SCKSyntaxHighlighter.m ├── SCKTextTypes.h ├── SCKTextTypes.m ├── SourceCodeKit-Info.plist ├── SourceCodeKit-Prefix.pch ├── SourceCodeKit.h └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | SourceCodeKit adaptation to modern objc/Mac OS X 2 | Unfortunately the original project seems to be abandon and no license was 3 | provided. Any modifications from the original source are covered under 4 | this licsense. 5 | 6 | You can find the original version here: 7 | http://svn.gna.org/svn/etoile/tags/Etoile-0.4.2/Languages/SourceCodeKit/ 8 | 9 | In order to compile this project a copy of libclang.a will be needed. 10 | 11 | Here is how you can build clang: 12 | http://clang.llvm.org/get_started.html 13 | 14 | Place the lib and include directories at the root of this project (or modify 15 | according to the location in which clang was built and installed) 16 | 17 | 18 | Copyright (c) 2013, Philippe Hausler 19 | All rights reserved. 20 | 21 | Redistribution and use in source and binary forms, with or without modification, 22 | are permitted provided that the following conditions are met: 23 | 24 | Redistributions of source code must retain the above copyright notice, this list 25 | of conditions and the following disclaimer. Redistributions in binary form must 26 | reproduce the above copyright notice, this list of conditions and the following 27 | disclaimer in the documentation and/or other materials provided with the 28 | distribution. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 31 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 34 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 35 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 37 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 38 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 | OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /SourceCodeKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5BDED1E316AB949B004FFC71 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BDED1E216AB949B004FFC71 /* Cocoa.framework */; }; 11 | 5BDED1ED16AB949B004FFC71 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5BDED1EB16AB949B004FFC71 /* InfoPlist.strings */; }; 12 | 5BDED20F16AB94EF004FFC71 /* SCKClangSourceFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED1FE16AB94EF004FFC71 /* SCKClangSourceFile.h */; }; 13 | 5BDED21016AB94EF004FFC71 /* SCKClangSourceFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED1FF16AB94EF004FFC71 /* SCKClangSourceFile.m */; }; 14 | 5BDED21116AB94EF004FFC71 /* SCKCodeCompletionResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20016AB94EF004FFC71 /* SCKCodeCompletionResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | 5BDED21216AB94EF004FFC71 /* SCKCodeCompletionResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED20116AB94EF004FFC71 /* SCKCodeCompletionResult.m */; }; 16 | 5BDED21316AB94EF004FFC71 /* SCKIntrospection.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20216AB94EF004FFC71 /* SCKIntrospection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 17 | 5BDED21416AB94EF004FFC71 /* SCKIntrospection.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED20316AB94EF004FFC71 /* SCKIntrospection.m */; }; 18 | 5BDED21516AB94EF004FFC71 /* SCKProject.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20416AB94EF004FFC71 /* SCKProject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | 5BDED21616AB94EF004FFC71 /* SCKProject.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED20516AB94EF004FFC71 /* SCKProject.m */; }; 20 | 5BDED21716AB94EF004FFC71 /* SCKSourceCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20616AB94EF004FFC71 /* SCKSourceCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | 5BDED21816AB94EF004FFC71 /* SCKSourceCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED20716AB94EF004FFC71 /* SCKSourceCollection.m */; }; 22 | 5BDED21916AB94EF004FFC71 /* SCKSourceFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20816AB94EF004FFC71 /* SCKSourceFile.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23 | 5BDED21A16AB94EF004FFC71 /* SCKSourceFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED20916AB94EF004FFC71 /* SCKSourceFile.m */; }; 24 | 5BDED21B16AB94EF004FFC71 /* SCKSyntaxHighlighter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20A16AB94EF004FFC71 /* SCKSyntaxHighlighter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25 | 5BDED21C16AB94EF004FFC71 /* SCKSyntaxHighlighter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED20B16AB94EF004FFC71 /* SCKSyntaxHighlighter.m */; }; 26 | 5BDED21D16AB94EF004FFC71 /* SCKTextTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20C16AB94EF004FFC71 /* SCKTextTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27 | 5BDED21E16AB94EF004FFC71 /* SCKTextTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BDED20D16AB94EF004FFC71 /* SCKTextTypes.m */; }; 28 | 5BDED21F16AB94EF004FFC71 /* SourceCodeKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDED20E16AB94EF004FFC71 /* SourceCodeKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29 | 5BDED22516AB9F1C004FFC71 /* libclang.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BDED22416AB9F1B004FFC71 /* libclang.a */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 5BDED1DF16AB949B004FFC71 /* SourceCodeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SourceCodeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 5BDED1E216AB949B004FFC71 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 35 | 5BDED1E516AB949B004FFC71 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 36 | 5BDED1E616AB949B004FFC71 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 37 | 5BDED1E716AB949B004FFC71 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 38 | 5BDED1EA16AB949B004FFC71 /* SourceCodeKit-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SourceCodeKit-Info.plist"; sourceTree = ""; }; 39 | 5BDED1EC16AB949B004FFC71 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 40 | 5BDED1EE16AB949B004FFC71 /* SourceCodeKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SourceCodeKit-Prefix.pch"; sourceTree = ""; }; 41 | 5BDED1FE16AB94EF004FFC71 /* SCKClangSourceFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKClangSourceFile.h; sourceTree = ""; }; 42 | 5BDED1FF16AB94EF004FFC71 /* SCKClangSourceFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKClangSourceFile.m; sourceTree = ""; }; 43 | 5BDED20016AB94EF004FFC71 /* SCKCodeCompletionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKCodeCompletionResult.h; sourceTree = ""; }; 44 | 5BDED20116AB94EF004FFC71 /* SCKCodeCompletionResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKCodeCompletionResult.m; sourceTree = ""; }; 45 | 5BDED20216AB94EF004FFC71 /* SCKIntrospection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKIntrospection.h; sourceTree = ""; }; 46 | 5BDED20316AB94EF004FFC71 /* SCKIntrospection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKIntrospection.m; sourceTree = ""; }; 47 | 5BDED20416AB94EF004FFC71 /* SCKProject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKProject.h; sourceTree = ""; }; 48 | 5BDED20516AB94EF004FFC71 /* SCKProject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKProject.m; sourceTree = ""; }; 49 | 5BDED20616AB94EF004FFC71 /* SCKSourceCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKSourceCollection.h; sourceTree = ""; }; 50 | 5BDED20716AB94EF004FFC71 /* SCKSourceCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKSourceCollection.m; sourceTree = ""; }; 51 | 5BDED20816AB94EF004FFC71 /* SCKSourceFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKSourceFile.h; sourceTree = ""; }; 52 | 5BDED20916AB94EF004FFC71 /* SCKSourceFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKSourceFile.m; sourceTree = ""; }; 53 | 5BDED20A16AB94EF004FFC71 /* SCKSyntaxHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKSyntaxHighlighter.h; sourceTree = ""; }; 54 | 5BDED20B16AB94EF004FFC71 /* SCKSyntaxHighlighter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKSyntaxHighlighter.m; sourceTree = ""; }; 55 | 5BDED20C16AB94EF004FFC71 /* SCKTextTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCKTextTypes.h; sourceTree = ""; }; 56 | 5BDED20D16AB94EF004FFC71 /* SCKTextTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCKTextTypes.m; sourceTree = ""; }; 57 | 5BDED20E16AB94EF004FFC71 /* SourceCodeKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceCodeKit.h; sourceTree = ""; }; 58 | 5BDED22416AB9F1B004FFC71 /* libclang.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libclang.a; path = lib/libclang.a; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 5BDED1DB16AB949A004FFC71 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | 5BDED22516AB9F1C004FFC71 /* libclang.a in Frameworks */, 67 | 5BDED1E316AB949B004FFC71 /* Cocoa.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXFrameworksBuildPhase section */ 72 | 73 | /* Begin PBXGroup section */ 74 | 5BDED1D316AB949A004FFC71 = { 75 | isa = PBXGroup; 76 | children = ( 77 | 5BDED1E816AB949B004FFC71 /* SourceCodeKit */, 78 | 5BDED1E116AB949B004FFC71 /* Frameworks */, 79 | 5BDED1E016AB949B004FFC71 /* Products */, 80 | ); 81 | sourceTree = ""; 82 | }; 83 | 5BDED1E016AB949B004FFC71 /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 5BDED1DF16AB949B004FFC71 /* SourceCodeKit.framework */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | 5BDED1E116AB949B004FFC71 /* Frameworks */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 5BDED22416AB9F1B004FFC71 /* libclang.a */, 95 | 5BDED1E216AB949B004FFC71 /* Cocoa.framework */, 96 | 5BDED1E416AB949B004FFC71 /* Other Frameworks */, 97 | ); 98 | name = Frameworks; 99 | sourceTree = ""; 100 | }; 101 | 5BDED1E416AB949B004FFC71 /* Other Frameworks */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 5BDED1E516AB949B004FFC71 /* AppKit.framework */, 105 | 5BDED1E616AB949B004FFC71 /* CoreData.framework */, 106 | 5BDED1E716AB949B004FFC71 /* Foundation.framework */, 107 | ); 108 | name = "Other Frameworks"; 109 | sourceTree = ""; 110 | }; 111 | 5BDED1E816AB949B004FFC71 /* SourceCodeKit */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 5BDED1FE16AB94EF004FFC71 /* SCKClangSourceFile.h */, 115 | 5BDED1FF16AB94EF004FFC71 /* SCKClangSourceFile.m */, 116 | 5BDED20016AB94EF004FFC71 /* SCKCodeCompletionResult.h */, 117 | 5BDED20116AB94EF004FFC71 /* SCKCodeCompletionResult.m */, 118 | 5BDED20216AB94EF004FFC71 /* SCKIntrospection.h */, 119 | 5BDED20316AB94EF004FFC71 /* SCKIntrospection.m */, 120 | 5BDED20416AB94EF004FFC71 /* SCKProject.h */, 121 | 5BDED20516AB94EF004FFC71 /* SCKProject.m */, 122 | 5BDED20616AB94EF004FFC71 /* SCKSourceCollection.h */, 123 | 5BDED20716AB94EF004FFC71 /* SCKSourceCollection.m */, 124 | 5BDED20816AB94EF004FFC71 /* SCKSourceFile.h */, 125 | 5BDED20916AB94EF004FFC71 /* SCKSourceFile.m */, 126 | 5BDED20A16AB94EF004FFC71 /* SCKSyntaxHighlighter.h */, 127 | 5BDED20B16AB94EF004FFC71 /* SCKSyntaxHighlighter.m */, 128 | 5BDED20C16AB94EF004FFC71 /* SCKTextTypes.h */, 129 | 5BDED20D16AB94EF004FFC71 /* SCKTextTypes.m */, 130 | 5BDED20E16AB94EF004FFC71 /* SourceCodeKit.h */, 131 | 5BDED1E916AB949B004FFC71 /* Supporting Files */, 132 | ); 133 | path = SourceCodeKit; 134 | sourceTree = ""; 135 | }; 136 | 5BDED1E916AB949B004FFC71 /* Supporting Files */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 5BDED1EA16AB949B004FFC71 /* SourceCodeKit-Info.plist */, 140 | 5BDED1EB16AB949B004FFC71 /* InfoPlist.strings */, 141 | 5BDED1EE16AB949B004FFC71 /* SourceCodeKit-Prefix.pch */, 142 | ); 143 | name = "Supporting Files"; 144 | sourceTree = ""; 145 | }; 146 | /* End PBXGroup section */ 147 | 148 | /* Begin PBXHeadersBuildPhase section */ 149 | 5BDED1DC16AB949A004FFC71 /* Headers */ = { 150 | isa = PBXHeadersBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | 5BDED20F16AB94EF004FFC71 /* SCKClangSourceFile.h in Headers */, 154 | 5BDED21116AB94EF004FFC71 /* SCKCodeCompletionResult.h in Headers */, 155 | 5BDED21316AB94EF004FFC71 /* SCKIntrospection.h in Headers */, 156 | 5BDED21516AB94EF004FFC71 /* SCKProject.h in Headers */, 157 | 5BDED21716AB94EF004FFC71 /* SCKSourceCollection.h in Headers */, 158 | 5BDED21916AB94EF004FFC71 /* SCKSourceFile.h in Headers */, 159 | 5BDED21B16AB94EF004FFC71 /* SCKSyntaxHighlighter.h in Headers */, 160 | 5BDED21D16AB94EF004FFC71 /* SCKTextTypes.h in Headers */, 161 | 5BDED21F16AB94EF004FFC71 /* SourceCodeKit.h in Headers */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXHeadersBuildPhase section */ 166 | 167 | /* Begin PBXNativeTarget section */ 168 | 5BDED1DE16AB949A004FFC71 /* SourceCodeKit */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = 5BDED1F416AB949B004FFC71 /* Build configuration list for PBXNativeTarget "SourceCodeKit" */; 171 | buildPhases = ( 172 | 5BDED1DA16AB949A004FFC71 /* Sources */, 173 | 5BDED1DB16AB949A004FFC71 /* Frameworks */, 174 | 5BDED1DC16AB949A004FFC71 /* Headers */, 175 | 5BDED1DD16AB949A004FFC71 /* Resources */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | ); 181 | name = SourceCodeKit; 182 | productName = SourceCodeKit; 183 | productReference = 5BDED1DF16AB949B004FFC71 /* SourceCodeKit.framework */; 184 | productType = "com.apple.product-type.framework"; 185 | }; 186 | /* End PBXNativeTarget section */ 187 | 188 | /* Begin PBXProject section */ 189 | 5BDED1D516AB949A004FFC71 /* Project object */ = { 190 | isa = PBXProject; 191 | attributes = { 192 | LastUpgradeCheck = 0450; 193 | ORGANIZATIONNAME = "Étoile"; 194 | }; 195 | buildConfigurationList = 5BDED1D816AB949A004FFC71 /* Build configuration list for PBXProject "SourceCodeKit" */; 196 | compatibilityVersion = "Xcode 3.2"; 197 | developmentRegion = English; 198 | hasScannedForEncodings = 0; 199 | knownRegions = ( 200 | en, 201 | ); 202 | mainGroup = 5BDED1D316AB949A004FFC71; 203 | productRefGroup = 5BDED1E016AB949B004FFC71 /* Products */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | 5BDED1DE16AB949A004FFC71 /* SourceCodeKit */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXResourcesBuildPhase section */ 213 | 5BDED1DD16AB949A004FFC71 /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 5BDED1ED16AB949B004FFC71 /* InfoPlist.strings in Resources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXResourcesBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | 5BDED1DA16AB949A004FFC71 /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 5BDED21016AB94EF004FFC71 /* SCKClangSourceFile.m in Sources */, 229 | 5BDED21216AB94EF004FFC71 /* SCKCodeCompletionResult.m in Sources */, 230 | 5BDED21416AB94EF004FFC71 /* SCKIntrospection.m in Sources */, 231 | 5BDED21616AB94EF004FFC71 /* SCKProject.m in Sources */, 232 | 5BDED21816AB94EF004FFC71 /* SCKSourceCollection.m in Sources */, 233 | 5BDED21A16AB94EF004FFC71 /* SCKSourceFile.m in Sources */, 234 | 5BDED21C16AB94EF004FFC71 /* SCKSyntaxHighlighter.m in Sources */, 235 | 5BDED21E16AB94EF004FFC71 /* SCKTextTypes.m in Sources */, 236 | ); 237 | runOnlyForDeploymentPostprocessing = 0; 238 | }; 239 | /* End PBXSourcesBuildPhase section */ 240 | 241 | /* Begin PBXVariantGroup section */ 242 | 5BDED1EB16AB949B004FFC71 /* InfoPlist.strings */ = { 243 | isa = PBXVariantGroup; 244 | children = ( 245 | 5BDED1EC16AB949B004FFC71 /* en */, 246 | ); 247 | name = InfoPlist.strings; 248 | sourceTree = ""; 249 | }; 250 | /* End PBXVariantGroup section */ 251 | 252 | /* Begin XCBuildConfiguration section */ 253 | 5BDED1F216AB949B004FFC71 /* Debug */ = { 254 | isa = XCBuildConfiguration; 255 | buildSettings = { 256 | ALWAYS_SEARCH_USER_PATHS = NO; 257 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 258 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 259 | CLANG_CXX_LIBRARY = "libc++"; 260 | CLANG_ENABLE_OBJC_ARC = YES; 261 | CLANG_WARN_EMPTY_BODY = YES; 262 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 263 | COPY_PHASE_STRIP = NO; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_DYNAMIC_NO_PIC = NO; 266 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 267 | GCC_OPTIMIZATION_LEVEL = 0; 268 | GCC_PREPROCESSOR_DEFINITIONS = ( 269 | "DEBUG=1", 270 | "$(inherited)", 271 | ); 272 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 273 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 274 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 275 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 276 | GCC_WARN_UNUSED_VARIABLE = YES; 277 | HEADER_SEARCH_PATHS = "\"$(SRCROOT)/include\""; 278 | LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/lib\""; 279 | MACOSX_DEPLOYMENT_TARGET = 10.8; 280 | ONLY_ACTIVE_ARCH = YES; 281 | SDKROOT = macosx; 282 | }; 283 | name = Debug; 284 | }; 285 | 5BDED1F316AB949B004FFC71 /* Release */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | ALWAYS_SEARCH_USER_PATHS = NO; 289 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 290 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 291 | CLANG_CXX_LIBRARY = "libc++"; 292 | CLANG_ENABLE_OBJC_ARC = YES; 293 | CLANG_WARN_EMPTY_BODY = YES; 294 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 295 | COPY_PHASE_STRIP = YES; 296 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 297 | GCC_C_LANGUAGE_STANDARD = gnu99; 298 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 299 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 300 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 301 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 302 | GCC_WARN_UNUSED_VARIABLE = YES; 303 | HEADER_SEARCH_PATHS = "\"$(SRCROOT)/include\""; 304 | LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/lib\""; 305 | MACOSX_DEPLOYMENT_TARGET = 10.8; 306 | SDKROOT = macosx; 307 | }; 308 | name = Release; 309 | }; 310 | 5BDED1F516AB949B004FFC71 /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | COMBINE_HIDPI_IMAGES = YES; 315 | DYLIB_COMPATIBILITY_VERSION = 1; 316 | DYLIB_CURRENT_VERSION = 1; 317 | FRAMEWORK_VERSION = A; 318 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 319 | GCC_PREFIX_HEADER = "SourceCodeKit/SourceCodeKit-Prefix.pch"; 320 | INFOPLIST_FILE = "SourceCodeKit/SourceCodeKit-Info.plist"; 321 | INSTALL_PATH = "@executable_path/../Frameworks"; 322 | LIBRARY_SEARCH_PATHS = ( 323 | "$(inherited)", 324 | "\"$(SRCROOT)/lib\"", 325 | ); 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | WRAPPER_EXTENSION = framework; 328 | }; 329 | name = Debug; 330 | }; 331 | 5BDED1F616AB949B004FFC71 /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | CLANG_ENABLE_OBJC_ARC = YES; 335 | COMBINE_HIDPI_IMAGES = YES; 336 | DYLIB_COMPATIBILITY_VERSION = 1; 337 | DYLIB_CURRENT_VERSION = 1; 338 | FRAMEWORK_VERSION = A; 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 340 | GCC_PREFIX_HEADER = "SourceCodeKit/SourceCodeKit-Prefix.pch"; 341 | INFOPLIST_FILE = "SourceCodeKit/SourceCodeKit-Info.plist"; 342 | INSTALL_PATH = "@executable_path/../Frameworks"; 343 | LIBRARY_SEARCH_PATHS = ( 344 | "$(inherited)", 345 | "\"$(SRCROOT)/lib\"", 346 | ); 347 | PRODUCT_NAME = "$(TARGET_NAME)"; 348 | WRAPPER_EXTENSION = framework; 349 | }; 350 | name = Release; 351 | }; 352 | /* End XCBuildConfiguration section */ 353 | 354 | /* Begin XCConfigurationList section */ 355 | 5BDED1D816AB949A004FFC71 /* Build configuration list for PBXProject "SourceCodeKit" */ = { 356 | isa = XCConfigurationList; 357 | buildConfigurations = ( 358 | 5BDED1F216AB949B004FFC71 /* Debug */, 359 | 5BDED1F316AB949B004FFC71 /* Release */, 360 | ); 361 | defaultConfigurationIsVisible = 0; 362 | defaultConfigurationName = Release; 363 | }; 364 | 5BDED1F416AB949B004FFC71 /* Build configuration list for PBXNativeTarget "SourceCodeKit" */ = { 365 | isa = XCConfigurationList; 366 | buildConfigurations = ( 367 | 5BDED1F516AB949B004FFC71 /* Debug */, 368 | 5BDED1F616AB949B004FFC71 /* Release */, 369 | ); 370 | defaultConfigurationIsVisible = 0; 371 | defaultConfigurationName = Release; 372 | }; 373 | /* End XCConfigurationList section */ 374 | }; 375 | rootObject = 5BDED1D516AB949A004FFC71 /* Project object */; 376 | } 377 | -------------------------------------------------------------------------------- /SourceCodeKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKClangSourceFile.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | @class SCKClangIndex; 6 | @class NSMutableArray; 7 | @class NSMutableAttributedString; 8 | 9 | /** 10 | * SCKSourceFile implementation that uses clang to perform handle 11 | * [Objective-]C[++] files. 12 | */ 13 | @interface SCKClangSourceFile : SCKSourceFile 14 | @property (nonatomic, readonly) NSMutableDictionary *classes; 15 | @property (nonatomic, readonly) NSMutableDictionary *functions; 16 | @property (nonatomic, readonly) NSMutableDictionary *globals; 17 | @property (nonatomic, readonly) NSMutableDictionary *enumerations; 18 | @property (nonatomic, readonly) NSMutableDictionary *enumerationValues; 19 | @end 20 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKClangSourceFile.m: -------------------------------------------------------------------------------- 1 | #import "SCKClangSourceFile.h" 2 | #import "SourceCodeKit.h" 3 | #import 4 | #include 5 | 6 | //#define NSLog(...) 7 | 8 | /** 9 | * Converts a clang source range into an NSRange within its enclosing file. 10 | */ 11 | NSRange NSRangeFromCXSourceRange(CXSourceRange sr) 12 | { 13 | unsigned start, end; 14 | CXSourceLocation s = clang_getRangeStart(sr); 15 | CXSourceLocation e = clang_getRangeEnd(sr); 16 | clang_getInstantiationLocation(s, 0, 0, 0, &start); 17 | clang_getInstantiationLocation(e, 0, 0, 0, &end); 18 | if (end < start) 19 | { 20 | return NSMakeRange(end, start-end); 21 | } 22 | return NSMakeRange(start, end - start); 23 | } 24 | 25 | static void freestring(CXString *str) 26 | { 27 | clang_disposeString(*str); 28 | } 29 | 30 | #define SCOPED_STR(name, value)\ 31 | __attribute__((unused))\ 32 | __attribute__((cleanup(freestring))) CXString name ## str = value;\ 33 | const char *name = clang_getCString(name ## str); 34 | 35 | @implementation SCKSourceLocation 36 | 37 | @synthesize file; 38 | @synthesize offset; 39 | 40 | - (id)initWithClangSourceLocation:(CXSourceLocation)l 41 | { 42 | self = [super init]; 43 | if (self) 44 | { 45 | CXFile f; 46 | unsigned o; 47 | clang_getInstantiationLocation(l, &f, 0, 0, &o); 48 | offset = o; 49 | SCOPED_STR(fileName, clang_getFileName(f)); 50 | file = [[NSString alloc] initWithUTF8String:fileName]; 51 | } 52 | return self; 53 | } 54 | 55 | - (NSString*)description 56 | { 57 | return [NSString stringWithFormat:@"%@:%d", file, (int)offset]; 58 | } 59 | 60 | - (NSUInteger)hash 61 | { 62 | return [file hash] ^ offset; 63 | } 64 | 65 | - (BOOL)isEqual:(id)object 66 | { 67 | if (object == self) 68 | { 69 | return YES; 70 | } 71 | 72 | if (![object isKindOfClass:[SCKSourceLocation class]]) 73 | { 74 | return NO; 75 | } 76 | 77 | if ([file isEqualToString:[(SCKSourceLocation *)object file]] && offset == [(SCKSourceLocation *)object offset]) 78 | { 79 | return YES; 80 | } 81 | 82 | return NO; 83 | } 84 | 85 | @end 86 | 87 | 88 | @interface SCKClangIndex : NSObject 89 | @property (readonly) CXIndex clangIndex; 90 | //FIXME: We should have different default arguments for C, C++ and ObjC. 91 | @property ( nonatomic) NSMutableArray *defaultArguments; 92 | @end 93 | 94 | @implementation SCKClangIndex 95 | 96 | @synthesize clangIndex, defaultArguments; 97 | 98 | - (id)init 99 | { 100 | self = [super init]; 101 | if (self) 102 | { 103 | clang_toggleCrashRecovery(0); 104 | clangIndex = clang_createIndex(1, 1); 105 | 106 | /* 107 | * NOTE: If BuildKit becomes usable, it might be sensible to store these 108 | * defaults in the BuildKit configuration and let BuildKit generate the 109 | * command line switches for us. 110 | */ 111 | NSString *plistPath = [[NSBundle bundleForClass:[SCKClangIndex class]] pathForResource:@"DefaultArguments" ofType:@"plist"]; 112 | 113 | NSData *plistData = [NSData dataWithContentsOfFile:plistPath]; 114 | 115 | // Load the options required to compile GNUstep apps 116 | defaultArguments = [(NSArray*)[NSPropertyListSerialization propertyListFromData:plistData 117 | mutabilityOption:NSPropertyListImmutable 118 | format:NULL 119 | errorDescription:NULL] mutableCopy]; 120 | } 121 | 122 | 123 | return self; 124 | } 125 | 126 | - (void)dealloc 127 | { 128 | clang_disposeIndex(clangIndex); 129 | } 130 | 131 | @end 132 | 133 | @interface SCKClangSourceFile () 134 | - (void)highlightRange:(CXSourceRange)r syntax:(BOOL)highightSyntax; 135 | @end 136 | 137 | @implementation SCKClangSourceFile { 138 | /** Compiler arguments */ 139 | NSMutableArray *args; 140 | /** Index shared between code files */ 141 | SCKClangIndex *idx; 142 | /** libclang translation unit handle. */ 143 | CXTranslationUnit translationUnit; 144 | CXFile file; 145 | } 146 | 147 | @synthesize classes, functions, globals, enumerations, enumerationValues; 148 | 149 | static NSString *classNameFromCategory(CXCursor category) 150 | { 151 | __block NSString *className = nil; 152 | clang_visitChildrenWithBlock(category, ^ enum CXChildVisitResult (CXCursor cursor, CXCursor parent) { 153 | if (CXCursor_ObjCClassRef == cursor.kind) 154 | { 155 | SCOPED_STR(name, clang_getCursorSpelling(cursor)); 156 | className = [NSString stringWithUTF8String:name]; 157 | return CXChildVisit_Break; 158 | } 159 | return CXChildVisit_Continue; 160 | }); 161 | return className; 162 | } 163 | 164 | - (void)setLocation:(SCKSourceLocation *)aLocation 165 | forMethod:(NSString *)methodName 166 | inClass:(NSString *)className 167 | category:(NSString *)categoryName 168 | isDefinition:(BOOL)isDefinition 169 | { 170 | SCKClass *cls = [classes objectForKey:className]; 171 | if (nil == cls) 172 | { 173 | cls = [SCKClass new]; 174 | cls.name = className; 175 | [classes setObject:cls forKey:className]; 176 | } 177 | 178 | NSMutableDictionary *methods = cls.methods; 179 | if (nil != categoryName) 180 | { 181 | SCKCategory *cat = [cls.categories objectForKey:categoryName]; 182 | if (nil == cat) 183 | { 184 | cat = [SCKCategory new]; 185 | cat.name = categoryName; 186 | cat.parent = cls; 187 | [cls.categories setObject:cat forKey:categoryName]; 188 | } 189 | methods = cat.methods; 190 | } 191 | 192 | SCKMethod *m = [methods objectForKey:methodName]; 193 | if (isDefinition) 194 | { 195 | m.definition = aLocation; 196 | } 197 | else 198 | { 199 | m.declaration = aLocation; 200 | } 201 | } 202 | - (void)setLocation:(SCKSourceLocation *)l 203 | forGlobal:(const char *)name 204 | withType:(const char *)type 205 | isFunction:(BOOL)isFunction 206 | isDefinition:(BOOL)isDefinition 207 | { 208 | NSMutableDictionary *dict = isFunction ? functions : globals; 209 | NSString *symbol = [NSString stringWithUTF8String:name]; 210 | 211 | SCKTypedProgramComponent *global = [dict objectForKey:symbol]; 212 | SCKTypedProgramComponent *g = nil; 213 | if (nil == global) 214 | { 215 | g = isFunction ? [SCKFunction new] : [SCKGlobal new]; 216 | global = g; 217 | global.name = symbol; 218 | [global setTypeEncoding:[NSString stringWithUTF8String:type]]; 219 | } 220 | 221 | if (isDefinition) 222 | { 223 | global.definition = l; 224 | } 225 | else 226 | { 227 | global.declaration = l; 228 | } 229 | 230 | [dict setObject:global forKey:symbol]; 231 | } 232 | 233 | - (void)rebuildIndex 234 | { 235 | if (0 == translationUnit) 236 | { 237 | return; 238 | } 239 | 240 | clang_visitChildrenWithBlock(clang_getTranslationUnitCursor(translationUnit), ^ enum CXChildVisitResult (CXCursor cursor, CXCursor parent) { 241 | switch(cursor.kind) 242 | { 243 | default: 244 | break; 245 | case CXCursor_ObjCImplementationDecl: { 246 | clang_visitChildrenWithBlock(clang_getTranslationUnitCursor(translationUnit), ^ enum CXChildVisitResult (CXCursor cursor, CXCursor parent) { 247 | if (CXCursor_ObjCInstanceMethodDecl == cursor.kind) 248 | { 249 | SCOPED_STR(methodName, clang_getCursorSpelling(cursor)); 250 | SCOPED_STR(className, clang_getCursorSpelling(parent)); 251 | //clang_visitChildren((parent), findClass, NULL); 252 | SCKSourceLocation *l = [[SCKSourceLocation alloc] initWithClangSourceLocation:clang_getCursorLocation(cursor)]; 253 | [self setLocation:l 254 | forMethod:[NSString stringWithUTF8String:methodName] 255 | inClass:[NSString stringWithUTF8String:className] 256 | category:nil 257 | isDefinition:clang_isCursorDefinition(cursor)]; 258 | } 259 | return CXChildVisit_Continue; 260 | }); 261 | break; 262 | } 263 | case CXCursor_ObjCCategoryImplDecl: { 264 | clang_visitChildrenWithBlock(clang_getTranslationUnitCursor(translationUnit), ^ enum CXChildVisitResult (CXCursor cursor, CXCursor parent) { 265 | if (CXCursor_ObjCInstanceMethodDecl == cursor.kind) 266 | { 267 | SCOPED_STR(methodName, clang_getCursorSpelling(cursor)); 268 | SCOPED_STR(categoryName, clang_getCursorSpelling(parent)); 269 | NSString *className = classNameFromCategory(parent); 270 | SCKSourceLocation *l = [[SCKSourceLocation alloc] initWithClangSourceLocation:clang_getCursorLocation(cursor)]; 271 | [self setLocation:l 272 | forMethod:[NSString stringWithUTF8String:methodName] 273 | inClass:className 274 | category:[NSString stringWithUTF8String:categoryName] 275 | isDefinition:clang_isCursorDefinition(cursor)]; 276 | } 277 | return CXChildVisit_Continue; 278 | }); 279 | break; 280 | } 281 | case CXCursor_FunctionDecl: 282 | case CXCursor_VarDecl: { 283 | if (clang_getCursorLinkage(cursor) == CXLinkage_External) 284 | { 285 | SCOPED_STR(name, clang_getCursorSpelling(cursor)); 286 | SCOPED_STR(type, clang_getDeclObjCTypeEncoding(cursor)); 287 | SCKSourceLocation *l = [[SCKSourceLocation alloc] initWithClangSourceLocation:clang_getCursorLocation(cursor)]; 288 | [self setLocation:l 289 | forGlobal:name 290 | withType:type 291 | isFunction:(cursor.kind == CXCursor_FunctionDecl) 292 | isDefinition:clang_isCursorDefinition(cursor)]; 293 | } 294 | break; 295 | } 296 | case CXCursor_EnumDecl: { 297 | SCOPED_STR(enumName, clang_getCursorSpelling(cursor)); 298 | SCOPED_STR(type, clang_getDeclObjCTypeEncoding(cursor)); 299 | NSString *name = [NSString stringWithUTF8String:enumName]; 300 | SCKEnumeration *e = [enumerations objectForKey:name]; 301 | 302 | __block BOOL foundType; 303 | if (e == nil) 304 | { 305 | e = [SCKEnumeration new]; 306 | foundType = NO; 307 | e.name = name; 308 | e.declaration = [[SCKSourceLocation alloc] initWithClangSourceLocation:clang_getCursorLocation(cursor)]; 309 | } 310 | else 311 | { 312 | foundType = e.typeEncoding != nil; 313 | } 314 | 315 | clang_visitChildrenWithBlock(cursor, ^ enum CXChildVisitResult (CXCursor enumCursor, CXCursor parent) { 316 | if (enumCursor.kind == CXCursor_EnumConstantDecl) 317 | { 318 | if (!foundType) 319 | { 320 | SCOPED_STR(type, clang_getDeclObjCTypeEncoding(enumCursor)); 321 | foundType = YES; 322 | e.typeEncoding = [NSString stringWithUTF8String:type]; 323 | } 324 | SCOPED_STR(valName, clang_getCursorSpelling(enumCursor)); 325 | NSString *vName = [NSString stringWithUTF8String:valName]; 326 | 327 | SCKEnumerationValue *v = [e.values objectForKey:vName]; 328 | if (nil == v) 329 | { 330 | v = [SCKEnumerationValue new]; 331 | v.name = vName; 332 | v.declaration = [[SCKSourceLocation alloc] initWithClangSourceLocation:clang_getCursorLocation(enumCursor)]; 333 | v.longLongValue = clang_getEnumConstantDeclValue(enumCursor); 334 | [e.values setObject:v forKey:vName]; 335 | } 336 | 337 | SCKEnumerationValue *ev = [enumerationValues objectForKey:vName]; 338 | if (ev) 339 | { 340 | if (ev.longLongValue != v.longLongValue) 341 | { 342 | [enumerationValues setObject:[NSMutableArray arrayWithObjects:v, ev, nil] forKey:vName]; 343 | } 344 | } 345 | else 346 | { 347 | [enumerationValues setObject:v forKey:vName]; 348 | } 349 | } 350 | return CXChildVisit_Continue; 351 | }); 352 | break; 353 | } 354 | } 355 | return CXChildVisit_Continue; 356 | }); 357 | } 358 | 359 | - (id)initUsingIndex:(SCKIndex *)anIndex 360 | { 361 | self = [super init]; 362 | if (self) 363 | { 364 | idx = (SCKClangIndex*)anIndex; 365 | NSAssert([idx isKindOfClass:[SCKClangIndex class]], @"Initializing SCKClangSourceFile with incorrect kind of index"); 366 | args = [idx.defaultArguments mutableCopy]; 367 | classes = [NSMutableDictionary new]; 368 | functions = [NSMutableDictionary new]; 369 | globals = [NSMutableDictionary new]; 370 | enumerations = [NSMutableDictionary new]; 371 | enumerationValues = [NSMutableDictionary new]; 372 | } 373 | return self; 374 | } 375 | 376 | - (void)addIncludePath:(NSString *)includePath 377 | { 378 | [args addObject:[NSString stringWithFormat:@"-I%@", includePath]]; 379 | // After we've added an include path, we may change how the file is parsed, 380 | // so parse it again, if required 381 | if (NULL != translationUnit) 382 | { 383 | clang_disposeTranslationUnit(translationUnit); 384 | translationUnit = NULL; 385 | [self reparse]; 386 | } 387 | } 388 | 389 | - (void)dealloc 390 | { 391 | if (NULL != translationUnit) 392 | { 393 | clang_disposeTranslationUnit(translationUnit); 394 | } 395 | } 396 | 397 | - (void)reparse 398 | { 399 | const char *fn = [fileName UTF8String]; 400 | struct CXUnsavedFile unsaved[] = { 401 | {fn, [[source string] UTF8String], [source length]}, 402 | {NULL, NULL, 0} 403 | }; 404 | 405 | int unsavedCount = (source == nil) ? 0 : 1; 406 | 407 | const char *mainFile = fn; 408 | if ([@"h" isEqualToString:[fileName pathExtension]]) 409 | { 410 | unsaved[unsavedCount].Filename = "/tmp/foo.m"; 411 | unsaved[unsavedCount].Contents = [[NSString stringWithFormat:@"#import \"%@\"\n", fileName] UTF8String]; 412 | unsaved[unsavedCount].Length = strlen(unsaved[unsavedCount].Contents); 413 | mainFile = unsaved[unsavedCount].Filename; 414 | unsavedCount++; 415 | } 416 | 417 | file = NULL; 418 | if (NULL == translationUnit) 419 | { 420 | int argc = (int)[args count]; 421 | const char *argv[argc]; 422 | int i=0; 423 | for (NSString *arg in args) 424 | { 425 | argv[i++] = [arg UTF8String]; 426 | } 427 | translationUnit =clang_parseTranslationUnit(idx.clangIndex, 428 | mainFile, argv, argc, unsaved, 429 | unsavedCount, 430 | clang_defaultEditingTranslationUnitOptions()); 431 | file = clang_getFile(translationUnit, fn); 432 | } 433 | else 434 | { 435 | if (0 != clang_reparseTranslationUnit(translationUnit, unsavedCount, unsaved, clang_defaultReparseOptions(translationUnit))) 436 | { 437 | clang_disposeTranslationUnit(translationUnit); 438 | translationUnit = 0; 439 | } 440 | else 441 | { 442 | file = clang_getFile(translationUnit, fn); 443 | } 444 | } 445 | [self rebuildIndex]; 446 | } 447 | 448 | - (void)lexicalHighlightFile 449 | { 450 | CXSourceLocation start = clang_getLocation(translationUnit, file, 1, 1); 451 | CXSourceLocation end = clang_getLocationForOffset(translationUnit, file, (unsigned int)[source length]); 452 | [self highlightRange:clang_getRange(start, end) syntax:NO]; 453 | } 454 | 455 | - (void)highlightRange:(CXSourceRange)r syntax:(BOOL)highightSyntax 456 | { 457 | NSString *TokenTypes[] = { 458 | SCKTextTokenTypePunctuation, 459 | SCKTextTokenTypeKeyword, 460 | SCKTextTokenTypeIdentifier, 461 | SCKTextTokenTypeLiteral, 462 | SCKTextTokenTypeComment 463 | }; 464 | 465 | if (clang_equalLocations(clang_getRangeStart(r), clang_getRangeEnd(r))) 466 | { 467 | NSLog(@"Range has no length!"); 468 | return; 469 | } 470 | 471 | CXToken *tokens; 472 | unsigned tokenCount; 473 | clang_tokenize(translationUnit, r , &tokens, &tokenCount); 474 | 475 | if (tokenCount > 0) 476 | { 477 | CXCursor *cursors = NULL; 478 | if (highightSyntax) 479 | { 480 | cursors = calloc(sizeof(CXCursor), tokenCount); 481 | clang_annotateTokens(translationUnit, tokens, tokenCount, cursors); 482 | } 483 | 484 | for (unsigned i = 0 ; i < tokenCount ; i++) 485 | { 486 | CXSourceRange sr = clang_getTokenExtent(translationUnit, tokens[i]); 487 | NSRange range = NSRangeFromCXSourceRange(sr); 488 | if (range.location > 0) 489 | { 490 | if ([[source string] characterAtIndex:range.location - 1] == '@') 491 | { 492 | range.location--; 493 | range.length++; 494 | } 495 | } 496 | 497 | if (highightSyntax) 498 | { 499 | id type; 500 | switch (cursors[i].kind) 501 | { 502 | case CXCursor_FirstRef... CXCursor_LastRef: 503 | type = SCKTextTypeReference; 504 | break; 505 | case CXCursor_MacroDefinition: 506 | type = SCKTextTypeMacroDefinition; 507 | break; 508 | case CXCursor_MacroInstantiation: 509 | type = SCKTextTypeMacroInstantiation; 510 | break; 511 | case CXCursor_FirstDecl...CXCursor_LastDecl: 512 | type = SCKTextTypeDeclaration; 513 | break; 514 | case CXCursor_ObjCMessageExpr: 515 | type = SCKTextTypeMessageSend; 516 | break; 517 | case CXCursor_DeclRefExpr: 518 | type = SCKTextTypeDeclRef; 519 | break; 520 | case CXCursor_PreprocessingDirective: 521 | type = SCKTextTypePreprocessorDirective; 522 | break; 523 | default: 524 | type = nil; 525 | } 526 | 527 | if (nil != type) 528 | { 529 | [source addAttribute:kSCKTextSemanticType 530 | value:type 531 | range:range]; 532 | } 533 | } 534 | [source addAttribute:kSCKTextTokenType 535 | value:TokenTypes[clang_getTokenKind(tokens[i])] 536 | range:range]; 537 | } 538 | 539 | clang_disposeTokens(translationUnit, tokens, tokenCount); 540 | free(cursors); 541 | } 542 | } 543 | 544 | - (void)syntaxHighlightRange:(NSRange)r 545 | { 546 | CXSourceLocation start = clang_getLocationForOffset(translationUnit, file, (unsigned int)r.location); 547 | CXSourceLocation end = clang_getLocationForOffset(translationUnit, file, (unsigned int)r.location + (unsigned int)r.length); 548 | [self highlightRange:clang_getRange(start, end) syntax:YES]; 549 | } 550 | 551 | - (void)syntaxHighlightFile 552 | { 553 | [self syntaxHighlightRange:NSMakeRange(0, [source length])]; 554 | } 555 | 556 | - (void)collectDiagnostics 557 | { 558 | unsigned diagnosticCount = clang_getNumDiagnostics(translationUnit); 559 | unsigned opts = clang_defaultDiagnosticDisplayOptions(); 560 | 561 | for (unsigned i=0 ; i 0) 566 | { 567 | CXString str = clang_getDiagnosticSpelling(d); 568 | CXSourceLocation loc = clang_getDiagnosticLocation(d); 569 | unsigned rangeCount = clang_getDiagnosticNumRanges(d); 570 | 571 | if (rangeCount == 0) { 572 | //FIXME: probably somewhat redundant 573 | SCKSourceLocation* sloc = [[SCKSourceLocation alloc] initWithClangSourceLocation:loc]; 574 | NSDictionary *attr = @{kSCKDiagnosticSeverity: @(s), 575 | kSCKDiagnosticText: [NSString stringWithUTF8String:clang_getCString(str)]}; 576 | 577 | NSRange r = NSMakeRange(sloc->offset, 1); 578 | 579 | [source addAttribute:kSCKDiagnostic 580 | value:attr 581 | range:r]; 582 | } 583 | for (unsigned j=0 ; jResults, cr->NumResults); 638 | 639 | for (unsigned i = 0 ; i < cr->NumResults; i++) 640 | { 641 | CXCompletionString cs = cr->Results[i].CompletionString; 642 | NSMutableAttributedString *completion = [NSMutableAttributedString new]; 643 | NSMutableString *s = [completion mutableString]; 644 | unsigned chunks = clang_getNumCompletionChunks(cs); 645 | for (unsigned j=0 ; j"]; 696 | break; 697 | case CXCompletionChunk_Comma: 698 | [s appendString:@","]; 699 | break; 700 | case CXCompletionChunk_ResultType: 701 | break; 702 | case CXCompletionChunk_Colon: 703 | [s appendString:@":"]; 704 | break; 705 | case CXCompletionChunk_SemiColon: 706 | [s appendString:@";"]; 707 | break; 708 | case CXCompletionChunk_Equal: 709 | [s appendString:@"="]; 710 | break; 711 | case CXCompletionChunk_HorizontalSpace: 712 | [s appendString:@" "]; 713 | break; 714 | case CXCompletionChunk_VerticalSpace: 715 | [s appendString:@"\n"]; 716 | break; 717 | } 718 | } 719 | [completions addObject:completion]; 720 | } 721 | result.completions = completions; 722 | clang_disposeCodeCompleteResults(cr); 723 | return result; 724 | } 725 | 726 | @end 727 | 728 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKCodeCompletionResult.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SCKCodeCompletionResult : NSObject 4 | @property (nonatomic, retain) NSString *fixitText; 5 | @property (nonatomic) NSRange fixitRange; 6 | @property (nonatomic, retain) NSArray *completions; 7 | @end 8 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKCodeCompletionResult.m: -------------------------------------------------------------------------------- 1 | #import "SCKCodeCompletionResult.h" 2 | 3 | @implementation SCKCodeCompletionResult 4 | @synthesize fixitText, fixitRange, completions; 5 | @end 6 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKIntrospection.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class NSString; 4 | @class NSAttributedString; 5 | @class SCKSourceLocation; 6 | @class NSMutableArray; 7 | @class NSMutableDictionary; 8 | 9 | /** 10 | * SCKProgramComponent is an abstract class representing properties of some 11 | * component of a program. This includes classes, functions, methods, and so 12 | * on. 13 | * 14 | * Program components in SourceCodeKit can be obtained both by runtime 15 | * introspection and by parsing source code. 16 | */ 17 | @interface SCKProgramComponent : NSObject 18 | /** 19 | * The name of this program component. 20 | */ 21 | @property (nonatomic, retain) NSString *name; 22 | /** 23 | * The location where the component is defined, if visible. 24 | */ 25 | @property (nonatomic, retain) SCKSourceLocation *definition; 26 | /** 27 | * The location where the component is declared, if visible. 28 | */ 29 | // FIXME: We should allow multiple declaration locations. 30 | @property (nonatomic, retain) SCKSourceLocation *declaration; 31 | /** 32 | * Documentation associated with this object. This may be generated by an IDE, 33 | * extracted from headers, or read from some external source. 34 | */ 35 | @property (nonatomic, retain) NSAttributedString *documentation; 36 | /** 37 | * The parent of this component. 38 | */ 39 | @property (nonatomic, unsafe_unretained) SCKProgramComponent *parent; 40 | @end 41 | 42 | /** 43 | * A program component with a type. 44 | */ 45 | @interface SCKTypedProgramComponent : SCKProgramComponent 46 | /** Objective-C type encoding of the component. */ 47 | @property (retain, nonatomic) NSString *typeEncoding; 48 | @end 49 | 50 | @interface SCKBundle : SCKProgramComponent 51 | /** 52 | * All of the public symbols exported by the bundle. 53 | */ 54 | @property (retain, nonatomic) NSMutableArray *classes; 55 | @property (retain, nonatomic) NSMutableArray *functions; 56 | @end 57 | 58 | @interface SCKClass : SCKProgramComponent 59 | @property (nonatomic, unsafe_unretained) SCKClass *superclass; 60 | @property (nonatomic, readonly, retain) NSMutableArray *subclasses; 61 | @property (nonatomic, readonly, retain) NSMutableDictionary *categories; 62 | @property (nonatomic, readonly, retain) NSMutableDictionary *methods; 63 | @property (nonatomic, readonly, retain) NSMutableArray *ivars; 64 | - (id)initWithClass:(Class)cls; 65 | @end 66 | 67 | @interface SCKCategory : SCKProgramComponent 68 | @property (nonatomic, readonly, retain) NSMutableDictionary *methods; 69 | @end 70 | 71 | @interface SCKMethod : SCKTypedProgramComponent 72 | @property (nonatomic) BOOL isClassMethod; 73 | @end 74 | 75 | @interface SCKIvar : SCKTypedProgramComponent 76 | @end 77 | 78 | @interface SCKFunction : SCKTypedProgramComponent 79 | @end 80 | 81 | @interface SCKGlobal : SCKTypedProgramComponent 82 | @end 83 | 84 | /** 85 | * Enumerated type value. This encapsulates the name and value of the 86 | * enumeration value. 87 | */ 88 | @interface SCKEnumerationValue : SCKProgramComponent 89 | /** 90 | * Returns the value of the enumeration. 91 | */ 92 | @property long long longLongValue; 93 | /** 94 | * The name of the enumeration. 95 | */ 96 | @property (nonatomic, retain) NSString *enumerationName; 97 | @end 98 | 99 | @interface SCKEnumeration : SCKTypedProgramComponent 100 | /** 101 | * Array of SCKEnumerationValue instances that describe the values in this 102 | * enumeration. 103 | */ 104 | @property (nonatomic, retain) NSMutableDictionary *values; 105 | @end 106 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKIntrospection.m: -------------------------------------------------------------------------------- 1 | #import "SourceCodeKit.h" 2 | #import 3 | 4 | @implementation SCKProgramComponent 5 | 6 | @synthesize parent, declaration, definition, documentation, name; 7 | 8 | - (id)initWithName:(NSString *)aName 9 | { 10 | self = [super init]; 11 | if (self) 12 | { 13 | name = [aName copy]; 14 | } 15 | return self; 16 | } 17 | 18 | - (NSString*)description 19 | { 20 | return name; 21 | } 22 | 23 | @end 24 | 25 | @implementation SCKBundle 26 | 27 | @synthesize classes, functions; 28 | 29 | - (id)init 30 | { 31 | self = [super init]; 32 | if (self) 33 | { 34 | classes = [NSMutableArray new]; 35 | functions = [NSMutableArray new]; 36 | } 37 | return self; 38 | } 39 | 40 | - (NSString*)description 41 | { 42 | NSMutableString *str = [self.name mutableCopy]; 43 | for (id function in functions) 44 | { 45 | [str appendFormat:@"\n\t%@", function]; 46 | } 47 | for (id class in classes) 48 | { 49 | [str appendFormat:@"\n\t%@", class]; 50 | } 51 | return str; 52 | } 53 | 54 | @end 55 | 56 | @implementation SCKClass 57 | 58 | @synthesize subclasses, superclass, categories, methods, ivars; 59 | 60 | - (id)init 61 | { 62 | self = [super init]; 63 | if (self) 64 | { 65 | subclasses = [NSMutableArray new]; 66 | categories = [NSMutableDictionary new]; 67 | methods = [NSMutableDictionary new]; 68 | ivars = [NSMutableArray new]; 69 | } 70 | return self; 71 | } 72 | 73 | - (id)initWithClass:(Class)cls 74 | { 75 | self = [super initWithName:[NSString stringWithUTF8String:class_getName(cls)]]; 76 | if (self) 77 | { 78 | unsigned int count; 79 | 80 | Ivar *ivarList = class_copyIvarList(cls, &count); 81 | for (unsigned int i = 0 ; i < count; i++) 82 | { 83 | SCKIvar *ivar = [SCKIvar new]; 84 | ivar.name = [NSString stringWithUTF8String:ivar_getName(ivarList[i])]; 85 | [ivar setTypeEncoding:[NSString stringWithUTF8String:ivar_getTypeEncoding(ivarList[i])]]; 86 | ivar.parent = self; 87 | [ivars addObject:ivar]; 88 | } 89 | if (count>0) 90 | { 91 | free(ivarList); 92 | } 93 | 94 | Method *methodList = class_copyMethodList(cls, &count); 95 | for (unsigned int i = 0 ; i < count; i++) 96 | { 97 | SCKMethod *method = [SCKMethod new]; 98 | method.name = [NSString stringWithUTF8String:sel_getName(method_getName(methodList[i]))]; 99 | [method setTypeEncoding:[NSString stringWithUTF8String:method_getTypeEncoding(methodList[i])]]; 100 | method.parent = self; 101 | [methods setObject:method forKey:method.name]; 102 | } 103 | if (count>0) 104 | { 105 | free(methodList); 106 | } 107 | } 108 | return self; 109 | } 110 | 111 | - (NSString*)description 112 | { 113 | NSMutableString *str = [self.name mutableCopy]; 114 | 115 | for (id ivar in ivars) 116 | { 117 | [str appendFormat:@"\n\t\t%@", ivar]; 118 | } 119 | 120 | for (id method in methods) 121 | { 122 | [str appendFormat:@"\n\t\t%@", method]; 123 | } 124 | 125 | return str; 126 | } 127 | 128 | @end 129 | 130 | @implementation SCKCategory : SCKProgramComponent 131 | 132 | @synthesize methods; 133 | 134 | - (id)init 135 | { 136 | self = [super init]; 137 | if (self) 138 | { 139 | methods = [NSMutableDictionary new]; 140 | } 141 | return self; 142 | } 143 | 144 | - (NSString*)description 145 | { 146 | NSMutableString *str = [NSMutableString stringWithFormat:@"%@ (%@)", self.parent.name, self.name]; 147 | for (id method in methods) 148 | { 149 | [str appendFormat:@"\n\t%@", method]; 150 | } 151 | return str; 152 | } 153 | 154 | @end 155 | 156 | @implementation SCKMethod 157 | @synthesize isClassMethod; 158 | - (NSString*)description 159 | { 160 | return [NSString stringWithFormat:@"%c%@", isClassMethod ? '+' : '-', self.name]; 161 | } 162 | @end 163 | 164 | @implementation SCKTypedProgramComponent 165 | @synthesize typeEncoding; 166 | @end 167 | 168 | @implementation SCKIvar @end 169 | @implementation SCKFunction @end 170 | @implementation SCKGlobal @end 171 | @implementation SCKEnumeration 172 | @synthesize values; 173 | @end 174 | @implementation SCKEnumerationValue 175 | @synthesize longLongValue, enumerationName; 176 | - (NSString*)description 177 | { 178 | return [NSString stringWithFormat:@"%@ (%lld)", self.name, longLongValue]; 179 | } 180 | @end 181 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKProject.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class SCKSourceCollection; 4 | 5 | /** 6 | * SCKProject represents an IDE project that tracks several source files usually 7 | * put together in a directory. 8 | * 9 | * In addition, SCKProject provides access to the program components declared 10 | * in the project files. See -classes, -functions and -globals. 11 | * 12 | * Custom presentation in the IDE source list (or similar UI) are supported by 13 | * setting a custom project content class, that implements the collection 14 | * protocols on the behalf of SCKProject instance. The collection returned by 15 | * -content depends on the class set with -setContentClass:. 16 | */ 17 | @interface SCKProject : NSObject 18 | 19 | /** 20 | * 21 | * Initializes and returns a new project based on the directory URL (to resolve 22 | * relative paths) and the provided source collection to retrieve the SCKFile 23 | * objects. 24 | * 25 | * A source collection can be shared between several projects (it caches SCKFile 26 | * objects). 27 | * 28 | * When aSourceCollection is nil, raises a NSInvalidArgumentException. 29 | */ 30 | - (id) initWithDirectoryURL: (NSURL *)aURL 31 | sourceCollection: (SCKSourceCollection *)aSourceCollection; 32 | 33 | /** 34 | * The project directory URL used to resolve relative paths (such as -fileURLs). 35 | */ 36 | @property (nonatomic, readonly) NSURL *directoryURL; 37 | /** 38 | * Returns the URLs of the files that belong to the project. 39 | */ 40 | @property (nonatomic, readonly) NSArray *fileURLs; 41 | 42 | @property (nonatomic, readonly) SCKSourceCollection *sourceCollection; 43 | 44 | /** 45 | * Adds the file that corresponds to the URL to the project. 46 | * 47 | * When the URL is nil, raises a NSInvalidArgumentException. 48 | */ 49 | - (void)addFileURL: (NSURL *)aURL; 50 | /** 51 | * Removes the file that corresponds to the URL from the project. 52 | * 53 | * When the URL is nil, raises a NSInvalidArgumentException. 54 | */ 55 | - (void)removeFileURL: (NSURL *)aURL; 56 | 57 | /** 58 | * The files that belong to the project. 59 | * 60 | * The returned array contains SCKFile objects. 61 | */ 62 | @property (nonatomic, readonly) NSArray *files; 63 | /** 64 | * All the classes declared in the files that belong to the project. 65 | * 66 | * The returned array contains SCKClass objects. 67 | */ 68 | @property (nonatomic, readonly) NSArray *classes; 69 | /** 70 | * All the functions declared in the files that belong to the project. 71 | * 72 | * The returned array contains SCKFunction objects. 73 | */ 74 | @property (nonatomic, readonly) NSArray *functions; 75 | /** 76 | * All the global variables declared in the files that belong to the project. 77 | * 78 | * The returned array contains SCKGlobal objects. 79 | */ 80 | @property (nonatomic, readonly) NSArray *globals; 81 | 82 | /** 83 | * The content class that controls the current content exposed through the 84 | * collection protocols. 85 | * 86 | * The content class must conform to SCKProjectContent protocol. 87 | */ 88 | @property (nonatomic) Class contentClass; 89 | 90 | @end 91 | 92 | 93 | /** 94 | * Protocol to which SCKProject content class must conform to. 95 | * See -[SCKProject setContentClass:]. 96 | */ 97 | @protocol SCKProjectContent 98 | - (id)content; 99 | @end 100 | 101 | /** 102 | * Content class to present the project files. 103 | */ 104 | @interface SCKFileBrowsingProjectContent : NSObject 105 | @end 106 | 107 | /** 108 | * Content class to present the project program components grouped into classes, 109 | * functions and globals. 110 | */ 111 | @interface SCKSymbolBrowsingProjectContent : NSObject 112 | @end 113 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKProject.m: -------------------------------------------------------------------------------- 1 | #import "SCKProject.h" 2 | #import "SCKSourceFile.h" 3 | #import "SCKSourceCollection.h" 4 | 5 | @implementation SCKProject 6 | { 7 | NSURL *directoryURL; 8 | SCKSourceCollection *sourceCollection; 9 | NSMutableArray *fileURLs; 10 | id projectContent; 11 | } 12 | 13 | @synthesize directoryURL, fileURLs; 14 | @synthesize sourceCollection; 15 | 16 | - (id)init 17 | { 18 | self = [super init]; 19 | if (self) 20 | { 21 | directoryURL = nil; 22 | sourceCollection = [[SCKSourceCollection alloc] init]; 23 | fileURLs = [[NSMutableArray alloc] init]; 24 | projectContent = [[SCKFileBrowsingProjectContent alloc] init]; 25 | } 26 | return self; 27 | } 28 | 29 | - (id) initWithDirectoryURL:(NSURL *)aURL 30 | sourceCollection:(SCKSourceCollection *)aSourceCollection; 31 | { 32 | NSAssert(aSourceCollection != nil, @"Collection must not be nil"); 33 | self = [super init]; 34 | if (self) 35 | { 36 | directoryURL = aURL; 37 | sourceCollection = aSourceCollection; 38 | fileURLs = [NSMutableArray new]; 39 | projectContent = [SCKFileBrowsingProjectContent new]; 40 | } 41 | return self; 42 | } 43 | 44 | - (void)addFileURL:(NSURL *)aURL 45 | { 46 | if (aURL == nil) 47 | { 48 | return; 49 | } 50 | 51 | if ([fileURLs containsObject:aURL]) 52 | return; 53 | 54 | [fileURLs addObject: aURL]; 55 | } 56 | 57 | - (void)removeFileURL:(NSURL *)aURL 58 | { 59 | if (aURL == nil) 60 | { 61 | return; 62 | } 63 | 64 | [fileURLs removeObject:aURL]; 65 | } 66 | 67 | - (NSArray *)files 68 | { 69 | NSMutableArray *files = [NSMutableArray new]; 70 | 71 | for (NSURL *url in fileURLs) 72 | { 73 | NSString *resolvedFilePath = (directoryURL == nil ? [url path] : [[directoryURL path] stringByAppendingPathComponent:[url relativePath]]); 74 | SCKSourceFile *file = [sourceCollection sourceFileForPath:[resolvedFilePath stringByStandardizingPath]]; 75 | 76 | [files addObject: file]; 77 | } 78 | return files; 79 | } 80 | 81 | - (NSArray *)programComponentsForKey:(NSString *)key 82 | { 83 | // NOTE: We could write... 84 | //NSDictionary *componentsByName = [[[self files] mappedCollection] valueForKey: key]; 85 | //return [[[componentsByName mappedCollection] allValues] flattenedCollection]; 86 | 87 | NSMutableArray *components = [NSMutableArray new]; 88 | for (SCKSourceFile *file in [self files]) 89 | { 90 | [components addObjectsFromArray:[[file valueForKey:key] allValues]]; 91 | } 92 | return components; 93 | } 94 | 95 | - (NSArray *)classes 96 | { 97 | return [self programComponentsForKey:@"classes"]; 98 | } 99 | 100 | - (NSArray *)functions 101 | { 102 | return [self programComponentsForKey:@"functions"]; 103 | } 104 | 105 | - (NSArray *)globals 106 | { 107 | return [self programComponentsForKey:@"globals"]; 108 | } 109 | 110 | - (void)setContentClass: (Class)aClass 111 | { 112 | NSAssert([aClass conformsToProtocol:@protocol(SCKProjectContent)], @"Content class must conform to SCKProjectContent protocol"); 113 | projectContent = [aClass new]; 114 | } 115 | 116 | - (Class)contentClass 117 | { 118 | return [projectContent class]; 119 | } 120 | 121 | - (id)content 122 | { 123 | return [projectContent content]; 124 | } 125 | 126 | @end 127 | 128 | @implementation SCKFileBrowsingProjectContent 129 | 130 | - (id)content 131 | { 132 | return nil; 133 | } 134 | 135 | @end -------------------------------------------------------------------------------- /SourceCodeKit/SCKSourceCollection.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class NSCache; 4 | @class NSMutableDictionary; 5 | @class SCKIndex; 6 | @class SCKSourceFile; 7 | 8 | /** 9 | * A source collection encapsulates a group of (potentially cross-referenced) 10 | * source code files. 11 | */ 12 | @interface SCKSourceCollection : NSObject 13 | { 14 | NSMutableDictionary *indexes; 15 | /** Files that have already been created. */ 16 | NSMutableDictionary *files; //TODO: turn back into NSCache 17 | NSMutableDictionary *bundleClasses; 18 | } 19 | @property (nonatomic, readonly, retain) NSMutableDictionary *classes; 20 | @property (nonatomic, readonly, retain) NSMutableDictionary *bundles; 21 | @property (nonatomic, readonly, retain) NSMutableDictionary *functions; 22 | @property (nonatomic, readonly, retain) NSMutableDictionary *globals; 23 | @property (nonatomic, readonly, retain) NSMutableDictionary *enumerations; 24 | @property (nonatomic, readonly, retain) NSMutableDictionary *enumerationValues; 25 | /** 26 | * Generates a new source file object corresponding to the specified on-disk 27 | * file. The returned object is not guaranteed to be unique - subsequent calls 28 | * with the same argument will return the same object. 29 | */ 30 | - (SCKSourceFile*)sourceFileForPath: (NSString*)aPath; 31 | - (SCKIndex*)indexForFileExtension: (NSString*)extension; 32 | @end 33 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKSourceCollection.m: -------------------------------------------------------------------------------- 1 | #import "SourceCodeKit.h" 2 | #import 3 | #import 4 | 5 | /** 6 | * Mapping from source file extensions to SCKSourceFile subclasses. 7 | */ 8 | static NSDictionary *fileClasses; 9 | 10 | @interface SCKClangIndex : NSObject 11 | @end 12 | 13 | @implementation SCKSourceCollection 14 | 15 | @synthesize bundles; 16 | 17 | + (void)initialize 18 | { 19 | Class clang = NSClassFromString(@"SCKClangSourceFile"); 20 | fileClasses = @{@"m": clang, 21 | @"cc": clang, 22 | @"c": clang, 23 | @"h": clang, 24 | @"cpp": clang}; 25 | } 26 | 27 | - (id)init 28 | { 29 | self = [super init]; 30 | indexes = [NSMutableDictionary new]; 31 | // A single clang index instance for all of the clang-supported file types 32 | id index = [SCKClangIndex new]; 33 | [indexes setObject:index forKey:@"m"]; 34 | [indexes setObject:index forKey:@"c"]; 35 | [indexes setObject:index forKey:@"h"]; 36 | [indexes setObject:index forKey:@"cpp"]; 37 | [indexes setObject:index forKey:@"cc"]; 38 | files = [NSMutableDictionary new]; 39 | bundles = [NSMutableDictionary new]; 40 | bundleClasses = [NSMutableDictionary new]; 41 | int count = objc_getClassList(NULL, 0); 42 | Class *classList = (__unsafe_unretained Class *)calloc(sizeof(Class), count); 43 | objc_getClassList(classList, count); 44 | for (int i = 0 ; i < count; i++) 45 | { 46 | SCKClass *cls = [[SCKClass alloc] initWithClass:classList[i]]; 47 | [bundleClasses setObject:cls forKey:[cls name]]; 48 | NSBundle *b = [NSBundle bundleForClass:classList[i]]; 49 | if (nil == b) 50 | { 51 | continue; 52 | } 53 | SCKBundle *bundle = [bundles objectForKey:[b bundlePath]]; 54 | if (nil == bundle) 55 | { 56 | bundle = [SCKBundle new]; 57 | bundle.name = [b bundlePath]; 58 | [bundles setObject:bundle forKey:[b bundlePath]]; 59 | } 60 | [bundle.classes addObject:cls]; 61 | } 62 | free(classList); 63 | return self; 64 | } 65 | 66 | - (NSMutableDictionary*)programComponentsFromFilesForKey:(NSString *)key 67 | { 68 | NSMutableDictionary *components = [NSMutableDictionary new]; 69 | for (SCKSourceFile *file in [files objectEnumerator]) 70 | { 71 | [components addEntriesFromDictionary:[file valueForKey:key]]; 72 | } 73 | return components; 74 | } 75 | 76 | - (NSDictionary*)classes 77 | { 78 | NSMutableDictionary* classes = [self programComponentsFromFilesForKey: @"classes"]; 79 | [classes addEntriesFromDictionary: bundleClasses]; 80 | return classes; 81 | } 82 | 83 | - (NSDictionary*)functions 84 | { 85 | return [self programComponentsFromFilesForKey: @"functions"]; 86 | } 87 | 88 | - (NSDictionary*)enumerationValues 89 | { 90 | return [self programComponentsFromFilesForKey: @"enumerationValues"]; 91 | } 92 | 93 | - (NSDictionary*)enumerations 94 | { 95 | return [self programComponentsFromFilesForKey: @"enumerations"]; 96 | } 97 | 98 | - (NSDictionary*)globals 99 | { 100 | return [self programComponentsFromFilesForKey: @"globals"]; 101 | } 102 | 103 | - (SCKIndex*)indexForFileExtension:(NSString *)extension 104 | { 105 | return [indexes objectForKey:extension]; 106 | } 107 | 108 | - (SCKSourceFile*)sourceFileForPath:(NSString *)aPath 109 | { 110 | NSString *path = [aPath stringByStandardizingPath]; 111 | 112 | SCKSourceFile *file = [files objectForKey:path]; 113 | if (nil != file) 114 | { 115 | return file; 116 | } 117 | 118 | NSString *extension = [path pathExtension]; 119 | file = [[fileClasses objectForKey:extension] fileUsingIndex: [indexes objectForKey:extension]]; 120 | file.fileName = path; 121 | file.collection = self; 122 | [file reparse]; 123 | if (nil != file) 124 | { 125 | [files setObject:file forKey:path]; 126 | } 127 | else 128 | { 129 | NSLog(@"Failed to load %@", path); 130 | } 131 | return file; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKSourceFile.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | @class SCKIndex; 5 | @class NSMutableArray; 6 | @class NSMutableAttributedString; 7 | @class SCKSourceCollection; 8 | @class SCKCodeCompletionResult; 9 | 10 | /** 11 | * The SCKSyntaxHighlighter class is responsible for performing lexical and 12 | * syntax highlighting on a single source file. Highlighting involves three steps: 13 | * 14 | * 1) Lexical markup. 15 | * 2) Syntax markup. 16 | * 3) Presentation markup. 17 | * 18 | * Lexical highlighting is faster than full syntax highlighting, so it can be 19 | * used more frequently in an editor. For example, you might run the lexical 20 | * highlighter after every key press but defer the syntax highlighter until 21 | * after a whitespace character had been entered. 22 | * 23 | * The third step is optional. If you are not using AppKit, then you can 24 | * ignore it and handle the presentation yourself. This is useful, for 25 | * example, when generating semantic HTML from a source file. 26 | */ 27 | @interface SCKSourceFile : NSObject 28 | { 29 | NSMutableAttributedString *source; 30 | NSString *fileName; 31 | } 32 | /** 33 | * Text storage object representing the source file. 34 | */ 35 | @property (retain, nonatomic) NSMutableAttributedString *source; 36 | /** 37 | * Name of this source file. 38 | */ 39 | @property (retain, nonatomic) NSString *fileName; 40 | /** 41 | * The source collection containing this file. 42 | */ 43 | @property (nonatomic, unsafe_unretained) SCKSourceCollection *collection; 44 | + (SCKSourceFile*)fileUsingIndex: (SCKIndex*)anIndex; 45 | /** 46 | * Parses the contents of the file. Must be called before reapplying 47 | * highlighting after the file has changed. 48 | */ 49 | - (void)reparse; 50 | /** 51 | * Performs lexical highlighting on the entire file. 52 | */ 53 | - (void)lexicalHighlightFile; 54 | /** 55 | * Perform syntax highlighting on the whole file. 56 | */ 57 | - (void)syntaxHighlightFile; 58 | /** 59 | * Performs syntax highlighting on the specified range. 60 | */ 61 | - (void)syntaxHighlightRange: (NSRange)r; 62 | /** 63 | * Adds an include path to search when performing syntax highlighting. 64 | */ 65 | - (void)addIncludePath: (NSString*)includePath; 66 | /** 67 | * Checks for errors and adds kSCKDiagnostic attributes to ranges in the source 68 | * attributed string which contain them. 69 | */ 70 | - (void)collectDiagnostics; 71 | /** 72 | * Returns completion result at the location 73 | */ 74 | - (SCKCodeCompletionResult*)completeAtLocation: (NSUInteger) location; 75 | @end 76 | 77 | @interface SCKSourceLocation : NSObject 78 | { 79 | @public 80 | NSString *file; 81 | NSUInteger offset; 82 | } 83 | @property (nonatomic, readonly) NSString *file; 84 | @property (nonatomic, readonly) NSUInteger offset; 85 | @end 86 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKSourceFile.m: -------------------------------------------------------------------------------- 1 | #import "SCKSourceFile.h" 2 | #import 3 | #import "SCKTextTypes.h" 4 | 5 | 6 | @implementation SCKSourceFile 7 | 8 | @synthesize fileName, source, collection; 9 | 10 | - (void)subclassResponsibility:(SEL)aSelector 11 | { 12 | NSLog(@"%@ must implement %s", [self class], sel_getName(aSelector)); 13 | } 14 | 15 | - (id)initUsingIndex:(SCKIndex *)anIndex 16 | { 17 | [self subclassResponsibility:_cmd]; 18 | self = nil; 19 | return nil; 20 | } 21 | 22 | + (SCKSourceFile*)fileUsingIndex:(SCKIndex *)anIndex 23 | { 24 | return [[self alloc] initUsingIndex: (SCKIndex*)anIndex]; 25 | } 26 | 27 | - (void)reparse 28 | { 29 | [self subclassResponsibility:_cmd]; 30 | } 31 | 32 | - (void)lexicalHighlightFile 33 | { 34 | [self subclassResponsibility:_cmd]; 35 | } 36 | 37 | - (void)syntaxHighlightFile 38 | { 39 | [self subclassResponsibility:_cmd]; 40 | } 41 | 42 | - (void)syntaxHighlightRange:(NSRange)r 43 | { 44 | [self subclassResponsibility:_cmd]; 45 | } 46 | 47 | - (void)addIncludePath:(NSString *)includePath 48 | { 49 | [self subclassResponsibility:_cmd]; 50 | } 51 | 52 | - (void)collectDiagnostics 53 | { 54 | [self subclassResponsibility:_cmd]; 55 | } 56 | 57 | - (SCKCodeCompletionResult*)completeAtLocation:(NSUInteger)location 58 | { 59 | [self subclassResponsibility:_cmd]; 60 | return nil; 61 | } 62 | 63 | @end 64 | 65 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKSyntaxHighlighter.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | @class NSMutableDictionary; 5 | @class NSMutableAttributedString; 6 | 7 | /** 8 | * The SCKSyntaxHighlighter class is responsible for mapping from the semantic 9 | * attributes defined by an SCKSourceFile subclass to (configurable) 10 | * presentation attributes. 11 | */ 12 | @interface SCKSyntaxHighlighter : NSObject 13 | /** 14 | * Attributes to be applied to token types. 15 | */ 16 | @property (retain, nonatomic) NSMutableDictionary *tokenAttributes; 17 | /** 18 | * Attributes to be applied to semantic types. 19 | */ 20 | @property (retain, nonatomic) NSMutableDictionary *semanticAttributes; 21 | /** 22 | * Transforms a source string, replacing the semantic attributes with 23 | * presentation attributes. 24 | */ 25 | - (void)transformString: (NSMutableAttributedString*)source; 26 | @end 27 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKSyntaxHighlighter.m: -------------------------------------------------------------------------------- 1 | #import "SCKSyntaxHighlighter.h" 2 | #import 3 | #import "SCKTextTypes.h" 4 | #include 5 | 6 | static NSDictionary *noAttributes; 7 | 8 | @implementation SCKSyntaxHighlighter 9 | 10 | @synthesize tokenAttributes, semanticAttributes; 11 | 12 | + (void)initialize 13 | { 14 | static dispatch_once_t once = 0L; 15 | dispatch_once(&once, ^{ 16 | noAttributes = [NSDictionary dictionary]; 17 | }); 18 | } 19 | 20 | - (id)init 21 | { 22 | self = [super init]; 23 | NSDictionary *comment = @{NSForegroundColorAttributeName: [NSColor grayColor]}; 24 | NSDictionary *keyword = @{NSForegroundColorAttributeName: [NSColor redColor]}; 25 | NSDictionary *literal = @{NSForegroundColorAttributeName: [NSColor redColor]}; 26 | tokenAttributes = [@{ 27 | SCKTextTokenTypeComment: comment, 28 | SCKTextTokenTypePunctuation: noAttributes, 29 | SCKTextTokenTypeKeyword: keyword, 30 | SCKTextTokenTypeLiteral: literal} 31 | mutableCopy]; 32 | 33 | semanticAttributes = [@{ 34 | SCKTextTypeDeclRef: @{NSForegroundColorAttributeName: [NSColor blueColor]}, 35 | SCKTextTypeMessageSend: @{NSForegroundColorAttributeName: [NSColor brownColor]}, 36 | SCKTextTypeDeclaration: @{NSForegroundColorAttributeName: [NSColor greenColor]}, 37 | SCKTextTypeMacroInstantiation: @{NSForegroundColorAttributeName: [NSColor magentaColor]}, 38 | SCKTextTypeMacroDefinition: @{NSForegroundColorAttributeName: [NSColor magentaColor]}, 39 | SCKTextTypePreprocessorDirective: @{NSForegroundColorAttributeName: [NSColor orangeColor]}, 40 | SCKTextTypeReference: @{NSForegroundColorAttributeName: [NSColor purpleColor]}} 41 | mutableCopy]; 42 | return self; 43 | } 44 | 45 | - (void)transformString:(NSMutableAttributedString *)source; 46 | { 47 | NSUInteger end = [source length]; 48 | NSUInteger i = 0; 49 | NSRange r; 50 | do 51 | { 52 | NSDictionary *attrs = [source attributesAtIndex:i 53 | longestEffectiveRange:&r 54 | inRange:NSMakeRange(i, end-i)]; 55 | i = r.location + r.length; 56 | 57 | NSString *token = [attrs objectForKey:kSCKTextTokenType]; 58 | NSString *semantic = [attrs objectForKey:kSCKTextSemanticType]; 59 | NSDictionary *diagnostic = [attrs objectForKey:kSCKDiagnostic]; 60 | 61 | // Skip ranges that have attributes other than semantic markup 62 | if ((nil == semantic) && (nil == token)) continue; 63 | if (semantic == SCKTextTypePreprocessorDirective) 64 | { 65 | attrs = [semanticAttributes objectForKey: semantic]; 66 | } 67 | else if (token == nil || token != SCKTextTokenTypeIdentifier) 68 | { 69 | attrs = [tokenAttributes objectForKey: token]; 70 | } 71 | else 72 | { 73 | NSString *semantic = [attrs objectForKey:kSCKTextSemanticType]; 74 | attrs = [semanticAttributes objectForKey:semantic]; 75 | } 76 | 77 | if (nil == attrs) 78 | { 79 | attrs = noAttributes; 80 | } 81 | 82 | [source setAttributes:attrs range:r]; 83 | 84 | // Re-apply the diagnostic 85 | if (nil != diagnostic) 86 | { 87 | [source addAttribute:NSToolTipAttributeName 88 | value:[diagnostic objectForKey: kSCKDiagnosticText] 89 | range:r]; 90 | [source addAttribute:NSUnderlineStyleAttributeName 91 | value:[NSNumber numberWithInt: NSSingleUnderlineStyle] 92 | range:r]; 93 | [source addAttribute:NSUnderlineColorAttributeName 94 | value:[NSColor redColor] 95 | range:r]; 96 | } 97 | } while (i < end); 98 | } 99 | 100 | @end 101 | 102 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKTextTypes.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | * The type of the token. This key indicates the type that lexical analysis 5 | * records for this token. 6 | */ 7 | NSString *const kSCKTextTokenType; 8 | /** 9 | * Token is punctuation. 10 | */ 11 | NSString *const SCKTextTokenTypePunctuation; 12 | /** 13 | * Token is a keyword. 14 | */ 15 | NSString *const SCKTextTokenTypeKeyword; 16 | /** 17 | * Token is an identifier. 18 | */ 19 | NSString *const SCKTextTokenTypeIdentifier; 20 | /** 21 | * Token is a literal value. 22 | */ 23 | NSString *const SCKTextTokenTypeLiteral; 24 | /** 25 | * Token is a comment. 26 | */ 27 | NSString *const SCKTextTokenTypeComment; 28 | /** 29 | * The type that semantic analysis records for this 30 | */ 31 | NSString *const kSCKTextSemanticType; 32 | /** 33 | * Reference to a type declared elsewhere. 34 | */ 35 | NSString *const SCKTextTypeReference; 36 | /** 37 | * Instantiation of a macro. 38 | */ 39 | NSString *const SCKTextTypeMacroInstantiation; 40 | /** 41 | * Definition of a macro. 42 | */ 43 | NSString *const SCKTextTypeMacroDefinition; 44 | /** 45 | * A declaration. 46 | */ 47 | NSString *const SCKTextTypeDeclaration; 48 | /** 49 | * A message send expression. 50 | */ 51 | NSString *const SCKTextTypeMessageSend; 52 | /** 53 | * A reference to a declaration. 54 | */ 55 | NSString *const SCKTextTypeDeclRef; 56 | /** 57 | * A preprocessor directive, such as #import or #include. 58 | */ 59 | NSString *const SCKTextTypePreprocessorDirective; 60 | /** 61 | * Something is wrong with the text for this range. The value for this 62 | * attribute is a dictionary describing exactly what. 63 | */ 64 | NSString *const kSCKDiagnostic; 65 | /** 66 | * The severity of the diagnostic. An NSNumber from 1 (hint) to 5 (fatal 67 | * error). 68 | */ 69 | NSString *const kSCKDiagnosticSeverity; 70 | /** 71 | * A human-readable string giving the text of the diagnostic, suitable for 72 | * display. 73 | */ 74 | NSString *const kSCKDiagnosticText; 75 | -------------------------------------------------------------------------------- /SourceCodeKit/SCKTextTypes.m: -------------------------------------------------------------------------------- 1 | #include "SCKTextTypes.h" 2 | 3 | NSString *const kSCKTextTokenType = @"kSCKTextTokenType"; 4 | NSString *const SCKTextTokenTypePunctuation = @"SCKTextTokenTypePunctuation"; 5 | NSString *const SCKTextTokenTypeKeyword = @"SCKTextTokenTypeKeyword"; 6 | NSString *const SCKTextTokenTypeIdentifier = @"SCKTextTokenTypeIdentifier"; 7 | NSString *const SCKTextTokenTypeLiteral = @"SCKTextTokenTypeLiteral"; 8 | NSString *const SCKTextTokenTypeComment = @"SCKTextTokenTypeComment"; 9 | NSString *const kSCKTextSemanticType = @"kSCKTextSemanticType"; 10 | NSString *const SCKTextTypeReference = @"SCKTextTypeReference"; 11 | NSString *const SCKTextTypeMacroInstantiation = @"SCKTextTypeMacroInstantiation"; 12 | NSString *const SCKTextTypeMacroDefinition = @"SCKTextTypeMacroDefinition"; 13 | NSString *const SCKTextTypeDeclaration = @"SCKTextTypeDeclaration"; 14 | NSString *const SCKTextTypeMessageSend = @"SCKTextTypeMessageSend"; 15 | NSString *const SCKTextTypeDeclRef = @"SCKTextTypeDeclRef"; 16 | NSString *const SCKTextTypePreprocessorDirective = @"SCKTextTypePreprocessorDirective"; 17 | NSString *const kSCKDiagnostic = @"kSCKDiagnostic"; 18 | NSString *const kSCKDiagnosticSeverity = @"kSCKDiagnosticSeverity"; 19 | NSString *const kSCKDiagnosticText = @"kSCKDiagnosticText"; 20 | -------------------------------------------------------------------------------- /SourceCodeKit/SourceCodeKit-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.etoileos.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SourceCodeKit/SourceCodeKit-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SourceCodeKit' target in the 'SourceCodeKit' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /SourceCodeKit/SourceCodeKit.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | #import 7 | #import 8 | -------------------------------------------------------------------------------- /SourceCodeKit/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------