├── Dependencies ├── GRMustache │ ├── LICENSE │ ├── RELEASE_NOTES.md │ ├── include │ │ ├── GRMustache.h │ │ ├── GRMustacheAvailabilityMacros.h │ │ ├── GRMustacheConfiguration.h │ │ ├── GRMustacheContext.h │ │ ├── GRMustacheError.h │ │ ├── GRMustacheFilter.h │ │ ├── GRMustacheLocalizer.h │ │ ├── GRMustacheRendering.h │ │ ├── GRMustacheTag.h │ │ ├── GRMustacheTagDelegate.h │ │ ├── GRMustacheTemplate.h │ │ ├── GRMustacheTemplateRepository.h │ │ ├── GRMustacheVersion.h │ │ ├── NSFormatter+GRMustache.h │ │ └── NSValueTransformer+GRMustache.h │ └── lib │ │ └── libGRMustache6-MacOS.a ├── LLVM │ ├── cfe-4.0.0.src.tar.xz │ ├── cfe-4.0.0.src.tar.xz.sig │ ├── llvm-4.0.0.src.tar.xz │ └── llvm-4.0.0.src.tar.xz.sig └── README.txt ├── LICENSE ├── ObjectDoc.xcodeproj └── project.pbxproj ├── ObjectDoc ├── ObjectDoc-Info.plist ├── ObjectDoc.h ├── ObjectDoc.mm ├── PLAdditions.h ├── PLClang.h ├── PLClang.m ├── PLClangAvailability.h ├── PLClangAvailability.m ├── PLClangAvailabilityPrivate.h ├── PLClangAvailabilityTests.m ├── PLClangComment.h ├── PLClangComment.m ├── PLClangCommentPrivate.h ├── PLClangCommentTests.m ├── PLClangCursor.h ├── PLClangCursor.m ├── PLClangCursorPrivate.h ├── PLClangCursorTests.m ├── PLClangDiagnostic.h ├── PLClangDiagnostic.m ├── PLClangDiagnosticPrivate.h ├── PLClangNSString.h ├── PLClangNSString.m ├── PLClangPlatformAvailability.h ├── PLClangPlatformAvailability.m ├── PLClangPlatformAvailabilityPrivate.h ├── PLClangSourceIndex.h ├── PLClangSourceIndex.m ├── PLClangSourceIndexTests.m ├── PLClangSourceLocation.h ├── PLClangSourceLocation.m ├── PLClangSourceLocationPrivate.h ├── PLClangSourceLocationTests.m ├── PLClangSourceRange.h ├── PLClangSourceRange.m ├── PLClangSourceRangePrivate.h ├── PLClangSourceRangeTests.m ├── PLClangTestCase.h ├── PLClangTestCase.m ├── PLClangToken.h ├── PLClangToken.m ├── PLClangTokenPrivate.h ├── PLClangTokenSet.h ├── PLClangTokenSet.m ├── PLClangTokenTests.m ├── PLClangTranslationUnit.h ├── PLClangTranslationUnit.m ├── PLClangTranslationUnitPrivate.h ├── PLClangTranslationUnitTests.m ├── PLClangType.h ├── PLClangType.m ├── PLClangTypePrivate.h ├── PLClangTypeTests.m ├── PLClangUnsavedFile.h ├── PLClangUnsavedFile.m ├── PLClangVersion.h ├── PLClangVersion.m ├── PLClangVersionPrivate.h ├── PLSourceLocation.h ├── PLSourceLocation.m └── en.lproj │ └── InfoPlist.strings ├── ObjectDocTests ├── en.lproj │ └── InfoPlist.strings └── objectdocTests-Info.plist └── doctool ├── DTApplication.h ├── DTApplication.m ├── DTConfiguration.h ├── DTConfiguration.m ├── DTDocSetGenerator.h ├── DTDocSetGenerator.m ├── DTDoxygenCommands.h ├── DTDoxygenCommands.m ├── DTGenerator.h ├── DTHTMLGenerator.h ├── DTHTMLGenerator.m ├── DTLibrary.h ├── DTLibrary.m ├── DTNode.h ├── DTNode.m ├── DTSourceParser.h ├── DTSourceParser.m ├── DTTask.h ├── DTTask.m ├── DocTool.h ├── DocTool.m ├── doctool-Info.plist ├── main.m └── templates ├── css └── docset.css ├── index.html ├── js └── docset.js ├── nodes.xml ├── objc_container.html ├── objc_node.html ├── token.xml └── tokens.xml /Dependencies/GRMustache/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Gwendal Roué 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustache.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | 26 | @protocol GRMustacheRendering; 27 | @class GRMustacheTag; 28 | @class GRMustacheContext; 29 | 30 | /** 31 | * A C struct that hold GRMustache version information 32 | * 33 | * @since v1.0 34 | */ 35 | typedef struct { 36 | int major; /**< The major component of the version. */ 37 | int minor; /**< The minor component of the version. */ 38 | int patch; /**< The patch-level component of the version. */ 39 | } GRMustacheVersion; 40 | 41 | 42 | /** 43 | * The GRMustache class provides with global-level information and configuration 44 | * of the GRMustache library. 45 | * 46 | * @since v1.0 47 | */ 48 | @interface GRMustache: NSObject 49 | 50 | //////////////////////////////////////////////////////////////////////////////// 51 | /// @name Getting the GRMustache version 52 | //////////////////////////////////////////////////////////////////////////////// 53 | 54 | /** 55 | * @return The version of GRMustache as a GRMustacheVersion struct. 56 | * 57 | * @since v1.0 58 | */ 59 | + (GRMustacheVersion)version AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 60 | 61 | 62 | //////////////////////////////////////////////////////////////////////////////// 63 | /// @name Preventing NSUndefinedKeyException in Development configuration 64 | //////////////////////////////////////////////////////////////////////////////// 65 | 66 | /** 67 | * Have GRMustache avoid most `NSUndefinedKeyExceptions` when rendering 68 | * templates. 69 | * 70 | * The rendering of a GRMustache template can lead to many 71 | * `NSUndefinedKeyExceptions` to be raised, because of the heavy usage of 72 | * Key-Value Coding. Those exceptions are nicely handled by GRMustache, and are 73 | * part of the regular rendering of a template. 74 | * 75 | * Unfortunately, when debugging a project, developers usually set their 76 | * debugger to stop on every Objective-C exceptions. GRMustache rendering can 77 | * thus become a huge annoyance. This method prevents it. 78 | * 79 | * You'll get a slight performance hit, so you'd probably make sure this call 80 | * does not enter your Release configuration. 81 | * 82 | * One way to achieve this is to add `-DDEBUG` to the "Other C Flags" setting of 83 | * your development configuration, and to wrap the 84 | * `preventNSUndefinedKeyExceptionAttack` method call in a #if block, like: 85 | * 86 | * #ifdef DEBUG 87 | * [GRMustache preventNSUndefinedKeyExceptionAttack]; 88 | * #endif 89 | * 90 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/runtime.md 91 | * 92 | * @since v1.7 93 | */ 94 | + (void)preventNSUndefinedKeyExceptionAttack AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 95 | 96 | 97 | //////////////////////////////////////////////////////////////////////////////// 98 | /// @name Standard Library 99 | //////////////////////////////////////////////////////////////////////////////// 100 | 101 | /** 102 | * @return The GRMustache standard library. 103 | * 104 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/standard_library.md 105 | * 106 | * @since v6.4 107 | */ 108 | + (NSObject *)standardLibrary AVAILABLE_GRMUSTACHE_VERSION_6_4_AND_LATER; 109 | 110 | 111 | //////////////////////////////////////////////////////////////////////////////// 112 | /// @name Building rendering objects 113 | //////////////////////////////////////////////////////////////////////////////// 114 | 115 | /** 116 | * Returns a rendering object that is able to render the argument _object_ for 117 | * the various Mustache tags. 118 | * 119 | * If _object_ already conforms to the GRMustacheRendering protocol, this method 120 | * returns _object_ itself: it is already able to render. 121 | * 122 | * For other values, including `nil`, this method returns a rendering object 123 | * that provides the default GRMustache rendering. 124 | * 125 | * @param object An object. 126 | * 127 | * @return A rendering object able to render the argument. 128 | * 129 | * @see GRMustacheRendering protocol 130 | * 131 | * @since v6.0 132 | */ 133 | + (id)renderingObjectForObject:(id)object AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 134 | 135 | /** 136 | * Returns a rendering object that renders with the provided block. 137 | * 138 | * @param block A block that follows the semantics of the 139 | * renderForMustacheTag:context:HTMLSafe:error: method defined by 140 | * the GRMustacheRendering protocol. See the documentation of this 141 | * method. 142 | * 143 | * @return A rendering object 144 | * 145 | * @see GRMustacheRendering protocol 146 | * 147 | * @since v6.0 148 | */ 149 | + (id)renderingObjectWithBlock:(NSString *(^)(GRMustacheTag *tag, GRMustacheContext *context, BOOL *HTMLSafe, NSError **error))block AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 150 | 151 | @end 152 | 153 | #import "GRMustacheTemplate.h" 154 | #import "GRMustacheTagDelegate.h" 155 | #import "GRMustacheTemplateRepository.h" 156 | #import "GRMustacheFilter.h" 157 | #import "GRMustacheError.h" 158 | #import "GRMustacheVersion.h" 159 | #import "GRMustacheContext.h" 160 | #import "GRMustacheRendering.h" 161 | #import "GRMustacheTag.h" 162 | #import "GRMustacheConfiguration.h" 163 | #import "GRMustacheLocalizer.h" 164 | #import "NSValueTransformer+GRMustache.h" 165 | #import "NSFormatter+GRMustache.h" 166 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustacheError.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | 26 | 27 | /** 28 | * The codes of a GRMustache-generated NSError 29 | * 30 | * @since v1.0 31 | */ 32 | typedef NS_ENUM(NSInteger, GRMustacheErrorCode) { 33 | /** 34 | * The error code for parse errors. 35 | * 36 | * @since v1.0 37 | */ 38 | GRMustacheErrorCodeParseError AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER, 39 | 40 | /** 41 | * The error code for not found templates and partials. 42 | * 43 | * @since v1.0 44 | */ 45 | GRMustacheErrorCodeTemplateNotFound AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER, 46 | 47 | /** 48 | * The error code for not rendering errors. 49 | * 50 | * @since v6.3 51 | */ 52 | GRMustacheErrorCodeRenderingError AVAILABLE_GRMUSTACHE_VERSION_6_3_AND_LATER, 53 | 54 | } AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 55 | 56 | 57 | /** 58 | * The domain of a GRMustache-generated NSError 59 | * 60 | * @since v1.0 61 | */ 62 | extern NSString *const GRMustacheErrorDomain AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 63 | 64 | 65 | /** 66 | * The name of exceptions raised by GRMustache when rendering a template. 67 | * 68 | * @since v5.1 69 | */ 70 | extern NSString *const GRMustacheRenderingException AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 71 | 72 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustacheFilter.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | 26 | 27 | // ============================================================================= 28 | #pragma mark - 29 | 30 | 31 | /** 32 | * The protocol for implementing GRMustache filters. 33 | * 34 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/runtime/filters.md 35 | * 36 | * The responsability of a GRMustacheFilter is to transform a value into 37 | * another. 38 | * 39 | * For example, the tag `{{ uppercase(name) }}` uses a filter object that 40 | * returns the uppercase version of its input. 41 | * 42 | * @since v4.3 43 | */ 44 | @protocol GRMustacheFilter 45 | @required 46 | 47 | //////////////////////////////////////////////////////////////////////////////// 48 | /// @name Transforming Values 49 | //////////////////////////////////////////////////////////////////////////////// 50 | 51 | /** 52 | * Applies some transformation to its input, and returns the transformed value. 53 | * 54 | * @param object An object to be processed by the filter. 55 | * 56 | * @return A transformed value. 57 | * 58 | * @since v4.3 59 | */ 60 | - (id)transformedValue:(id)object AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 61 | 62 | @end 63 | 64 | 65 | 66 | // ============================================================================= 67 | #pragma mark - GRMustacheFilter 68 | 69 | /** 70 | * The GRMustacheFilter class helps building mustache filters without writing a 71 | * custom class that conforms to the GRMustacheFilter protocol. 72 | * 73 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/runtime/filters.md 74 | * 75 | * @see GRMustacheFilter protocol 76 | * 77 | * @since v4.3 78 | */ 79 | @interface GRMustacheFilter : NSObject 80 | 81 | //////////////////////////////////////////////////////////////////////////////// 82 | /// @name Creating Filters 83 | //////////////////////////////////////////////////////////////////////////////// 84 | 85 | /** 86 | * Returns a GRMustacheFilter object that executes the provided block when 87 | * tranforming a value. 88 | * 89 | * @param block The block that transforms its input. 90 | * 91 | * @return a GRMustacheFilter object. 92 | * 93 | * @since v4.3 94 | * 95 | * @see variadicFilterWithBlock: 96 | */ 97 | + (id)filterWithBlock:(id(^)(id value))block AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 98 | 99 | /** 100 | * Returns a GRMustacheFilter object that executes the provided block, given an 101 | * array of arguments. 102 | * 103 | * Those filters can evaluate expressions like `{{ f(a,b) }}`. 104 | * 105 | * GRMustache will invoke the filter regardless of the number of arguments in 106 | * the template: `{{ f(a) }}`, `{{ f(a,b) }}` and `{{ f(a,b,c) }}` will provide 107 | * arrays of 1, 2, and 3 arguments respectively. It is your responsability to 108 | * check that you are provided with as many arguments as you expect. 109 | * 110 | * @param block The block that transforms its input. 111 | * 112 | * @return a GRMustacheFilter object. 113 | * 114 | * @since v5.5 115 | * 116 | * @see filterWithBlock: 117 | */ 118 | + (id)variadicFilterWithBlock:(id(^)(NSArray *arguments))block AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustacheLocalizer.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | #import "GRMustacheRendering.h" 26 | #import "GRMustacheFilter.h" 27 | 28 | /** 29 | * GRMustacheLocalizer can localize the content of a Mustache section. 30 | * It also has a filter facet that localizes your data. 31 | * 32 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/standard_library.md#localize 33 | * 34 | * The GRMustache standard library has a `localize` key which returns a 35 | * GRMustacheLocalizer that localizes just like the NSLocalizableString macro 36 | * does: with the Localizable.strings table of the main bundle. 37 | * 38 | * ### Localizing data: 39 | * 40 | * `{{ localize(greeting) }}` renders `NSLocalizedString(@"Hello", nil)`, 41 | * assuming the `greeting` key resolves to the @"Hello" string. 42 | * 43 | * ### Localizing sections: 44 | * 45 | * `{{#localize}}Hello{{/localize}}` renders `NSLocalizedString(@"Hello", nil)`. 46 | * 47 | * ### Localizing sections with arguments: 48 | * 49 | * `{{#localize}}Hello {{name}}{{/localize}}` builds the format string 50 | * @"Hello %@", localizes it with NSLocalizedString, and finally 51 | * injects the name with `[NSString stringWithFormat:]`. 52 | * 53 | * ### Localize sections with arguments and conditions: 54 | * 55 | * `{{#localize}}Good morning {{#title}}{{title}}{{/title}} {{name}}{{/localize}}` 56 | * build the format string @"Good morning %@" or @"Good morning %@ %@", 57 | * depending on the presence of the `title` key. It then injects the name, or 58 | * both title and name, with `[NSString stringWithFormat:]`, to build the final 59 | * rendering. 60 | * 61 | * ### Custom GRMustacheLocalizer 62 | * 63 | * You can build your own localizing helper with the initWithBundle:tableName: 64 | * method. The helper would then localize using the specified table from the 65 | * specified bundle. 66 | * 67 | * @since v6.4 68 | */ 69 | @interface GRMustacheLocalizer : NSObject { 70 | @private 71 | NSBundle *_bundle; 72 | NSString *_tableName; 73 | NSMutableArray *_formatArguments; 74 | } 75 | 76 | /** 77 | * Returns an initialized localizing helper. 78 | * 79 | * @param bundle The bundle where to look for localized strings. If nil, the 80 | * main bundle is used. 81 | * @param tableName The table where to look for localized strings. If nil, the 82 | * default Localizable.strings table would be searched. 83 | * 84 | * @return A newly initialized localizing helper. 85 | * 86 | * @since v6.4 87 | */ 88 | - (id)initWithBundle:(NSBundle *)bundle tableName:(NSString *)tableName AVAILABLE_GRMUSTACHE_VERSION_6_4_AND_LATER; 89 | 90 | /** 91 | * The bundle where to look for localized strings. 92 | * 93 | * @since v6.4 94 | */ 95 | @property (nonatomic, retain, readonly) NSBundle *bundle AVAILABLE_GRMUSTACHE_VERSION_6_4_AND_LATER; 96 | 97 | /** 98 | * The table where to look for localized strings. 99 | * 100 | * If nil, the default Localizable.strings table would be searched. 101 | * 102 | * @since v6.4 103 | */ 104 | @property (nonatomic, retain, readonly) NSString *tableName AVAILABLE_GRMUSTACHE_VERSION_6_4_AND_LATER; 105 | 106 | @end 107 | 108 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustacheRendering.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | 26 | @class GRMustacheContext; 27 | @class GRMustacheTag; 28 | 29 | /** 30 | * The protocol for your own objects that perform custom rendering. 31 | * 32 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/rendering_objects.md 33 | */ 34 | @protocol GRMustacheRendering 35 | 36 | /** 37 | * This method is invoked when the receiver should be rendered by a Mustache 38 | * tag. 39 | * 40 | * It returns three values: the rendering itself, a boolean that says whether 41 | * the rendering is HTML-safe or not, and an eventual error. 42 | * 43 | * Input values are the tag that should be rendered, and the context object that 44 | * represents the current context stack. 45 | * 46 | * Depending on the content type of the currently rendered template, an output 47 | * parameter _HTMLSafe_ set to NO will have the returned string HTML-escaped. 48 | * 49 | * @param tag The tag to be rendered 50 | * @param context A context for rendering inner tags. 51 | * @param HTMLSafe Upon return contains YES if the result is HTML-safe. 52 | * @param error If there is an error performing the rendering, upon return 53 | * contains an NSError object that describes the problem. 54 | * 55 | * @return The rendering of the receiver for the given tag, in the given 56 | * context. 57 | * 58 | * @see GRMustacheTag 59 | * @see GRMustacheContext 60 | * @see GRMustacheContentType 61 | */ 62 | - (NSString *)renderForMustacheTag:(GRMustacheTag *)tag 63 | context:(GRMustacheContext *)context 64 | HTMLSafe:(BOOL *)HTMLSafe 65 | error:(NSError **)error AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustacheTag.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | #import "GRMustacheConfiguration.h" 26 | 27 | @class GRMustacheTemplateRepository; 28 | 29 | /** 30 | * The types of Mustache tags 31 | * 32 | * @since v6.0 33 | */ 34 | typedef NS_ENUM(NSUInteger, GRMustacheTagType) { 35 | /** 36 | * The type for variable tags such as {{ name }} 37 | * 38 | * @since v6.0 39 | */ 40 | GRMustacheTagTypeVariable = 1 << 1 AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER, 41 | 42 | /** 43 | * The type for section tags such as {{# name }}...{{/}} 44 | * 45 | * @since v6.0 46 | */ 47 | GRMustacheTagTypeSection = 1 << 2 AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER, 48 | 49 | /** 50 | * The type for overridable section tags such as {{$ name }}...{{/}} 51 | * 52 | * @since v6.0 53 | */ 54 | GRMustacheTagTypeOverridableSection = 1 << 3 AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER, 55 | 56 | /** 57 | * The type for inverted section tags such as {{^ name }}...{{/}} 58 | * 59 | * @since v6.0 60 | */ 61 | GRMustacheTagTypeInvertedSection = 1 << 4 AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER, 62 | } AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 63 | 64 | 65 | /** 66 | * GRMustacheTag instances represent Mustache tags that render values, such as 67 | * a variable tag `{{ name }}`, or a section tag `{{# name }}...{{/ })`. 68 | * 69 | * **Companion guides:** 70 | * 71 | * - https://github.com/groue/GRMustache/blob/master/Guides/delegate.md 72 | * - https://github.com/groue/GRMustache/blob/master/Guides/rendering_objects.md 73 | */ 74 | @interface GRMustacheTag: NSObject { 75 | @private 76 | GRMustacheTagType _type; 77 | id _expression; 78 | GRMustacheTemplateRepository *_templateRepository; 79 | GRMustacheContentType _contentType; 80 | } 81 | 82 | 83 | //////////////////////////////////////////////////////////////////////////////// 84 | /// @name Tag Information 85 | //////////////////////////////////////////////////////////////////////////////// 86 | 87 | 88 | /** 89 | * The type of the tag 90 | */ 91 | @property (nonatomic, readonly) GRMustacheTagType type AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 92 | 93 | /** 94 | * Returns the literal and unprocessed inner content of the tag. 95 | * 96 | * A section tag such as `{{# name }}...{{/}}` returns @"...". 97 | * 98 | * Variable tags such as `{{ name }}` have no inner content: their inner 99 | * template string is the empty string. 100 | */ 101 | @property (nonatomic, readonly) NSString *innerTemplateString AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 102 | 103 | /** 104 | * Returns the description of the tag. 105 | * 106 | * For example: 107 | * 108 | * 109 | */ 110 | - (NSString *)description; 111 | 112 | //////////////////////////////////////////////////////////////////////////////// 113 | /// @name Methods Dedicated to the GRMustacheRendering Protocol 114 | //////////////////////////////////////////////////////////////////////////////// 115 | 116 | /** 117 | * The template repository that did provide the template string from which the 118 | * receiver tag has been extracted. 119 | * 120 | * This method is intended for objects conforming to the GRMustacheRendering 121 | * protocol who deal with templates including partial templates that come from 122 | * various template repositories. 123 | * 124 | * Caveat: Make sure you own (retain) template repositories. Don't use templates 125 | * returned by methods like `[GRMustacheTemplate templateFrom...]`: they return 126 | * autoreleased templates with an implicit autoreleased repository that will 127 | * eventually be deallocated when your rendering object tries to access it. 128 | * 129 | * @see GRMustacheRendering 130 | * @see GRMustacheTemplateRepository 131 | */ 132 | @property (nonatomic, readonly) GRMustacheTemplateRepository *templateRepository AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 133 | 134 | /** 135 | * Returns the rendering of the tag's inner content, rendering all inner 136 | * Mustache tags with the rendering context argument. 137 | * 138 | * This method is intended for objects conforming to the GRMustacheRendering 139 | * protocol. The following Guides show some use cases for this method: 140 | * 141 | * - https://github.com/groue/GRMustache/blob/master/Guides/delegate.md 142 | * - https://github.com/groue/GRMustache/blob/master/Guides/rendering_objects.md 143 | * - https://github.com/groue/GRMustache/blob/master/Guides/sample_code/indexes.md 144 | * 145 | * Note that variable tags such as `{{ name }}` have no inner content, and 146 | * return the empty string. 147 | * 148 | * @param context A context for rendering inner tags. 149 | * @param HTMLSafe Upon return contains YES or NO, depending on the content 150 | * type of the tag's template, as set by the configuration of 151 | * the source template repository. HTML templates yield YES, 152 | * text templates yield NO. 153 | * @param error If there is an error rendering the tag, upon return contains 154 | * an NSError object that describes the problem. 155 | * 156 | * @see GRMustacheRendering 157 | * @see GRMustacheContext 158 | * 159 | * @return The rendering of the tag's inner content. 160 | */ 161 | - (NSString *)renderContentWithContext:(GRMustacheContext *)context HTMLSafe:(BOOL *)HTMLSafe error:(NSError **)error AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustacheTagDelegate.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | 26 | @class GRMustacheTemplate; 27 | @class GRMustacheInvocation; 28 | @class GRMustacheTag; 29 | 30 | /** 31 | * Objects conforming to the GRMustacheTagDelegate protocol can observe and 32 | * alter, the rendering of Mustache tags. 33 | * 34 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/delegate.md 35 | * 36 | * @since v6.0 37 | */ 38 | @protocol GRMustacheTagDelegate 39 | @optional 40 | 41 | /** 42 | * Sent before a Mustache tag renders. 43 | * 44 | * This method gives an opportunity to alter objects that are rendered. 45 | * 46 | * For example, it is implemented by the NSFormatter class, in templates like 47 | * `{{# dateFormatter }}...{{ value }}...{{ value }}... {{/}}`. 48 | * 49 | * @param tag The Mustache tag about to render. 50 | * @param object The object about to be rendered. 51 | * 52 | * @return The object that should be rendered. 53 | * 54 | * @see GRMustacheTag 55 | * 56 | * @since v6.0 57 | */ 58 | - (id)mustacheTag:(GRMustacheTag *)tag willRenderObject:(id)object AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 59 | 60 | /** 61 | * Sent after a Mustache tag has rendered. 62 | * 63 | * @param tag The Mustache tag that has just rendered. 64 | * @param object The rendered object. 65 | * @param rendering The actual rendering 66 | * 67 | * @see GRMustacheTag 68 | * 69 | * @since v6.0 70 | */ 71 | - (void)mustacheTag:(GRMustacheTag *)tag didRenderObject:(id)object as:(NSString *)rendering AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 72 | 73 | /** 74 | * Sent right after a Mustache tag has failed rendering. 75 | * 76 | * @param tag The Mustache tag that has just failed rendering. 77 | * @param object The rendered object. 78 | * @param error The error. 79 | * 80 | * @see GRMustacheTag 81 | * 82 | * @since v6.0 83 | */ 84 | - (void)mustacheTag:(GRMustacheTag *)tag didFailRenderingObject:(id)object withError:(NSError *)error AVAILABLE_GRMUSTACHE_VERSION_6_0_AND_LATER; 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/GRMustacheVersion.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | 24 | /** 25 | * The major component of GRMustache version 26 | * 27 | * @since v1.0 28 | */ 29 | #define GRMUSTACHE_MAJOR_VERSION 6 30 | 31 | /** 32 | * The minor component of GRMustache version 33 | * 34 | * @since v1.0 35 | */ 36 | #define GRMUSTACHE_MINOR_VERSION 8 37 | 38 | /** 39 | * The patch-level component of GRMustache version 40 | * 41 | * @since v1.0 42 | */ 43 | #define GRMUSTACHE_PATCH_VERSION 2 44 | 45 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/NSFormatter+GRMustache.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | #import "GRMustacheRendering.h" 26 | #import "GRMustacheFilter.h" 27 | #import "GRMustacheTagDelegate.h" 28 | 29 | /** 30 | * A category on NSFormatter that allows them to be directly used in GRMustache 31 | * templates. 32 | * 33 | * **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/NSFormatter.md 34 | * 35 | * All NSFormatter subclasses such as NSDateFormatter, NSNumberFormatter, and 36 | * your custom subclasses are concerned. 37 | * 38 | * ## Filter facet 39 | * 40 | * A formatter can be used as a filter, as in `{{ percent(value) }}`. Just have 41 | * your `percent` key evaluate to a formatter. 42 | * 43 | * ## Formatting all values in a section 44 | * 45 | * A formatter can be used to format all values in a section of a template: 46 | * 47 | * {{# percent }}...{{ value1 }}...{{ value2 }}...{{/ percent }} 48 | * 49 | * The formatting then applies to all inner variable tags that evaluate to a 50 | * value that can be processed by the filter (see 51 | * [NSFormatter stringForObjectValue:] documentation). 52 | * 53 | * Inner loops and boolean sections are unaffected. However their inner variable 54 | * tags are: 55 | * 56 | * {{# percent }} 57 | * {{ value1 }} {{! format applies }} 58 | * {{# condition }} {{! format does not apply }} 59 | * {{ value2 }} {{! format applies }} 60 | * {{/ condition }} 61 | * {{/ percent }} 62 | * 63 | * @since v6.4 64 | */ 65 | @interface NSFormatter (GRMustache) 66 | @end 67 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/include/NSValueTransformer+GRMustache.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2013 Gwendal Roué 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "GRMustacheAvailabilityMacros.h" 25 | #import "GRMustacheFilter.h" 26 | 27 | /** 28 | * A category on NSValueTransformer that allows them to be directly used as 29 | * filters in GRMustache templates. 30 | * 31 | * @since v6.4 32 | */ 33 | @interface NSValueTransformer (GRMustache) 34 | @end 35 | -------------------------------------------------------------------------------- /Dependencies/GRMustache/lib/libGRMustache6-MacOS.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/objectdoc/4984c02574a7f699821d4df9c2234610737b760d/Dependencies/GRMustache/lib/libGRMustache6-MacOS.a -------------------------------------------------------------------------------- /Dependencies/LLVM/cfe-4.0.0.src.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/objectdoc/4984c02574a7f699821d4df9c2234610737b760d/Dependencies/LLVM/cfe-4.0.0.src.tar.xz -------------------------------------------------------------------------------- /Dependencies/LLVM/cfe-4.0.0.src.tar.xz.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/objectdoc/4984c02574a7f699821d4df9c2234610737b760d/Dependencies/LLVM/cfe-4.0.0.src.tar.xz.sig -------------------------------------------------------------------------------- /Dependencies/LLVM/llvm-4.0.0.src.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/objectdoc/4984c02574a7f699821d4df9c2234610737b760d/Dependencies/LLVM/llvm-4.0.0.src.tar.xz -------------------------------------------------------------------------------- /Dependencies/LLVM/llvm-4.0.0.src.tar.xz.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/objectdoc/4984c02574a7f699821d4df9c2234610737b760d/Dependencies/LLVM/llvm-4.0.0.src.tar.xz.sig -------------------------------------------------------------------------------- /Dependencies/README.txt: -------------------------------------------------------------------------------- 1 | GRMustache 2 | Description: 3 | Mustache templating engine. 4 | 5 | Version: 6 | 6.8.2 downloaded from https://github.com/groue/GRMustache/releases/tag/v6.8.2 7 | 8 | License: 9 | MIT 10 | 11 | LLVM 12 | Description: 13 | LLVM and Clang sources. 14 | 15 | Version: 16 | 4.0 downloaded from http://releases.llvm.org/download.html 17 | 18 | License: 19 | "UIUC" BSD-Style license 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 - 2013 Plausible Labs Cooperative, Inc. 2 | All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /ObjectDoc/ObjectDoc-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | coop.plausible.${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 | NSHumanReadableCopyright 26 | Copyright © 2013 Landon Fuller. All rights reserved. 27 | NSPrincipalClass 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ObjectDoc/ObjectDoc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | 31 | #import "PLClang.h" 32 | -------------------------------------------------------------------------------- /ObjectDoc/ObjectDoc.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import "ObjectDoc.h" 30 | -------------------------------------------------------------------------------- /ObjectDoc/PLAdditions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | /** 9 | * @defgroup API Additions and Extensions 10 | */ 11 | 12 | 13 | #ifndef PLSuperInit 14 | 15 | /** 16 | * @ingroup macros 17 | * 18 | * Call the superclass' default zero-argument initializer, returning nil if the superclass' initializer 19 | * returns nil. 20 | * 21 | * This macro is equivalent to: 22 | * 23 | * @code 24 | * if ((self = [super init]) == nil) 25 | * return nil; 26 | * @endcode 27 | * 28 | * @par Example Usage 29 | * 30 | * @code 31 | * - (id) initWithString { 32 | * PLSuperInit(); 33 | * } 34 | * @endcode 35 | */ 36 | #define PLSuperInit() do { \ 37 | if ((self = [super init]) == nil) {\ 38 | return nil; \ 39 | } \ 40 | } while (NO) 41 | 42 | #endif /* !PLSuperInit */ 43 | -------------------------------------------------------------------------------- /ObjectDoc/PLClang.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | extern NSString * const PLClangErrorDomain; 9 | 10 | /** 11 | * Error codes in the PLClangErrorDomain. 12 | */ 13 | typedef NS_ENUM(NSInteger, PLClangErrorCode) { 14 | /** 15 | * An unknown error occurred. 16 | * 17 | * If this error code is received it is a bug and should be reported. 18 | */ 19 | PLClangErrorUnknown = 0, 20 | 21 | /** 22 | * An unrecoverable compiler error occurred. 23 | */ 24 | PLClangErrorCompiler = 1, 25 | 26 | /** 27 | * Indicates that an error occurred while writing a translation unit to disk. 28 | */ 29 | PLClangErrorSaveFailed = 2, 30 | 31 | /** 32 | * Indicates that the specified translation unit was invalid. 33 | */ 34 | PLClangErrorInvalidTranslationUnit = 3 35 | }; 36 | 37 | #import "PLClangSourceIndex.h" 38 | 39 | FOUNDATION_EXPORT NSString *PLClangGetVersionString(); 40 | -------------------------------------------------------------------------------- /ObjectDoc/PLClang.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClang.h" 7 | #import "PLClangNSString.h" 8 | 9 | /** 10 | * The PLClang error domain. 11 | */ 12 | NSString * const PLClangErrorDomain = @"PLClangErrorDomain"; 13 | 14 | /** 15 | * Returns the Clang version as a string. 16 | * 17 | * @return The Clang version as a string suitable for displaying to the user. The string 18 | * is not suitable for parsing as the format is not guaranteed to be stable. 19 | */ 20 | NSString *PLClangGetVersionString() { 21 | return plclang_convert_and_dispose_cxstring(clang_getClangVersion()); 22 | } 23 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangAvailability.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangPlatformAvailability.h" 8 | 9 | /** 10 | * The availability kind of an entity. 11 | */ 12 | typedef NS_ENUM(NSUInteger, PLClangAvailabilityKind) { 13 | /** 14 | * The entity is available. 15 | */ 16 | PLClangAvailabilityKindAvailable = 0, 17 | 18 | /** 19 | * The entity is available, but deprecated. 20 | */ 21 | PLClangAvailabilityKindDeprecated = 1, 22 | 23 | /** 24 | * The entity is unavailable. 25 | */ 26 | PLClangAvailabilityKindUnavailable = 2, 27 | 28 | /** 29 | * The entity is available, but inaccessible. 30 | */ 31 | PLClangAvailabilityKindInaccessible = 3 32 | }; 33 | 34 | @interface PLClangAvailability : NSObject 35 | 36 | /** 37 | * The overall availability kind of the entity. 38 | * 39 | * This takes into account both unconditional deprecation and unavailability attributes as well as those 40 | * specific to the target platform. 41 | */ 42 | @property(nonatomic, readonly) PLClangAvailabilityKind kind; 43 | 44 | /** 45 | * A Boolean value indicating whether the entity is deprecated on all platforms. 46 | */ 47 | @property(nonatomic, readonly) BOOL isUnconditionallyDeprecated; 48 | 49 | /** 50 | * The message provided along with the unconditional deprecation of the entity, or nil if no message was provided. 51 | */ 52 | @property(nonatomic, readonly) NSString *unconditionalDeprecationMessage; 53 | 54 | /** 55 | * A Boolean value indicating whether the entity is unavailable on all platforms. 56 | */ 57 | @property(nonatomic, readonly) BOOL isUnconditionallyUnavailable; 58 | 59 | /** 60 | * The message provided along with the unconditional unavailability of the entity, or nil if no message was provided. 61 | */ 62 | @property(nonatomic, readonly) NSString *unconditionalUnavailabilityMessage; 63 | 64 | /** 65 | * An array of PLClangPlatformAvailability objects with plaform-specific availability information. 66 | */ 67 | @property(nonatomic, readonly) NSArray *platformAvailabilityEntries; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangAvailability.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangAvailability.h" 7 | #import "PLClangAvailabilityPrivate.h" 8 | #import "PLClangPlatformAvailabilityPrivate.h" 9 | #import "PLClangNSString.h" 10 | #import "PLAdditions.h" 11 | 12 | /** 13 | * Availability information for an entity. 14 | */ 15 | @implementation PLClangAvailability 16 | 17 | - (NSString *) description { 18 | NSMutableString *string = [NSMutableString string]; 19 | 20 | switch (self.kind) { 21 | case PLClangAvailabilityKindAvailable: 22 | { 23 | [string appendString: @"available"]; 24 | break; 25 | } 26 | 27 | case PLClangAvailabilityKindDeprecated: 28 | { 29 | [string appendString: @"deprecated"]; 30 | if ([self.unconditionalDeprecationMessage length] > 0) { 31 | [string appendFormat: @": \"%@\"", self.unconditionalDeprecationMessage]; 32 | } 33 | break; 34 | } 35 | 36 | case PLClangAvailabilityKindUnavailable: 37 | { 38 | [string appendString: @"unavailable"]; 39 | if ([self.unconditionalUnavailabilityMessage length] > 0) { 40 | [string appendFormat: @": \"%@\"", self.unconditionalUnavailabilityMessage]; 41 | } 42 | break; 43 | } 44 | 45 | case PLClangAvailabilityKindInaccessible: 46 | { 47 | [string appendString: @"inaccessible"]; 48 | break; 49 | } 50 | } 51 | 52 | if ([self.platformAvailabilityEntries count] > 0) { 53 | [string appendFormat: @"\n%@", self.platformAvailabilityEntries]; 54 | } 55 | 56 | return string; 57 | } 58 | 59 | @end 60 | 61 | /** 62 | * @internal 63 | * Package-private methods. 64 | */ 65 | @implementation PLClangAvailability (PackagePrivate) 66 | 67 | /** 68 | * Initialize a newly-created availability instance with the specified clang cursor. 69 | * 70 | * @param cursor The clang cursor that will provide availability information. 71 | * @return An initialized availability instance. 72 | */ 73 | - (instancetype) initWithCXCursor: (CXCursor) cursor { 74 | PLSuperInit(); 75 | 76 | _kind = [self availabilityKindForCXAvailabilityKind: clang_getCursorAvailability(cursor)]; 77 | 78 | // Get the number of platform availability entries 79 | int platformCount = clang_getCursorPlatformAvailability(cursor, NULL, NULL, NULL, NULL, NULL, 0); 80 | NSAssert(platformCount >= 0, @"clang_getCursorPlatformAvailability() returned a negative number of platforms"); 81 | 82 | int always_deprecated = 0; 83 | int always_unavailable = 0; 84 | CXString deprecationString = {}; 85 | CXString unavilableString = {}; 86 | CXPlatformAvailability *platformAvailability = calloc((unsigned int)platformCount, sizeof(CXPlatformAvailability)); 87 | clang_getCursorPlatformAvailability(cursor, 88 | &always_deprecated, 89 | &deprecationString, 90 | &always_unavailable, 91 | &unavilableString, 92 | platformAvailability, 93 | platformCount); 94 | 95 | _isUnconditionallyDeprecated = always_deprecated; 96 | _isUnconditionallyUnavailable = always_unavailable; 97 | _unconditionalDeprecationMessage = plclang_convert_and_dispose_cxstring(deprecationString); 98 | _unconditionalUnavailabilityMessage = plclang_convert_and_dispose_cxstring(unavilableString); 99 | 100 | NSMutableArray *entries = [NSMutableArray array]; 101 | 102 | for (int i = 0; i < platformCount; i++) { 103 | PLClangPlatformAvailability *availability = [[PLClangPlatformAvailability alloc] initWithCXPlatformAvailability: platformAvailability[i]]; 104 | [entries addObject: availability]; 105 | clang_disposeCXPlatformAvailability(&platformAvailability[i]); 106 | } 107 | 108 | _platformAvailabilityEntries = [entries copy]; 109 | free(platformAvailability); 110 | 111 | return self; 112 | } 113 | 114 | - (PLClangAvailabilityKind) availabilityKindForCXAvailabilityKind: (enum CXAvailabilityKind) cxAvailabilityKind { 115 | switch (cxAvailabilityKind) { 116 | case CXAvailability_Available: 117 | return PLClangAvailabilityKindAvailable; 118 | 119 | case CXAvailability_Deprecated: 120 | return PLClangAvailabilityKindDeprecated; 121 | 122 | case CXAvailability_NotAvailable: 123 | return PLClangAvailabilityKindUnavailable; 124 | 125 | case CXAvailability_NotAccessible: 126 | return PLClangAvailabilityKindInaccessible; 127 | } 128 | 129 | abort(); 130 | } 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangAvailabilityPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangAvailability.h" 8 | 9 | #import 10 | 11 | @interface PLClangAvailability (PackagePrivate) 12 | 13 | - (instancetype) initWithCXCursor: (CXCursor) cursor; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangAvailabilityTests.m: -------------------------------------------------------------------------------- 1 | #import "PLClangTestCase.h" 2 | 3 | @interface PLClangAvailabilityTests : PLClangTestCase 4 | @end 5 | 6 | @implementation PLClangAvailabilityTests 7 | 8 | - (void) testNoAvailability { 9 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f();"]; 10 | PLClangCursor *cursor = [tu cursorWithSpelling: @"f"]; 11 | XCTAssertNotNil(cursor); 12 | XCTAssertEqual(cursor.availability.kind, PLClangAvailabilityKindAvailable); 13 | XCTAssertFalse(cursor.availability.isUnconditionallyDeprecated); 14 | XCTAssertFalse(cursor.availability.isUnconditionallyUnavailable); 15 | XCTAssertEqualObjects(cursor.availability.unconditionalDeprecationMessage, @""); 16 | XCTAssertEqualObjects(cursor.availability.unconditionalUnavailabilityMessage, @""); 17 | XCTAssertTrue([cursor.availability.platformAvailabilityEntries count] == 0); 18 | } 19 | 20 | - (void) testDeprecatedAttribute { 21 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f() __attribute__((deprecated(\"message\")));"]; 22 | PLClangCursor *cursor = [tu cursorWithSpelling: @"f"]; 23 | XCTAssertNotNil(cursor); 24 | XCTAssertEqual(cursor.availability.kind, PLClangAvailabilityKindDeprecated); 25 | XCTAssertTrue(cursor.availability.isUnconditionallyDeprecated); 26 | XCTAssertFalse(cursor.availability.isUnconditionallyUnavailable); 27 | XCTAssertEqualObjects(cursor.availability.unconditionalDeprecationMessage, @"message"); 28 | XCTAssertEqualObjects(cursor.availability.unconditionalUnavailabilityMessage, @""); 29 | XCTAssertTrue([cursor.availability.platformAvailabilityEntries count] == 0); 30 | 31 | tu = [self translationUnitWithSource: @"void f() __attribute__((deprecated));"]; 32 | cursor = [tu cursorWithSpelling: @"f"]; 33 | XCTAssertNotNil(cursor); 34 | XCTAssertTrue(cursor.availability.isUnconditionallyDeprecated); 35 | XCTAssertEqualObjects(cursor.availability.unconditionalDeprecationMessage, @""); 36 | } 37 | 38 | - (void) testUnavailableAttribute { 39 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f() __attribute__((unavailable(\"message\")));"]; 40 | PLClangCursor *cursor = [tu cursorWithSpelling: @"f"]; 41 | XCTAssertNotNil(cursor); 42 | XCTAssertEqual(cursor.availability.kind, PLClangAvailabilityKindUnavailable); 43 | XCTAssertFalse(cursor.availability.isUnconditionallyDeprecated); 44 | XCTAssertTrue(cursor.availability.isUnconditionallyUnavailable); 45 | XCTAssertEqualObjects(cursor.availability.unconditionalDeprecationMessage, @""); 46 | XCTAssertEqualObjects(cursor.availability.unconditionalUnavailabilityMessage, @"message"); 47 | XCTAssertTrue([cursor.availability.platformAvailabilityEntries count] == 0); 48 | 49 | tu = [self translationUnitWithSource: @"void f() __attribute__((unavailable));"]; 50 | cursor = [tu cursorWithSpelling: @"f"]; 51 | XCTAssertNotNil(cursor); 52 | XCTAssertTrue(cursor.availability.isUnconditionallyUnavailable); 53 | XCTAssertEqualObjects(cursor.availability.unconditionalUnavailabilityMessage, @""); 54 | } 55 | 56 | - (void) testDeprecatedAndUnavailable { 57 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f() __attribute__((deprecated(\"deprecated\"))) __attribute__((unavailable(\"unavailable\")));"]; 58 | PLClangCursor *cursor = [tu cursorWithSpelling: @"f"]; 59 | XCTAssertNotNil(cursor); 60 | XCTAssertEqual(cursor.availability.kind, PLClangAvailabilityKindUnavailable); 61 | XCTAssertTrue(cursor.availability.isUnconditionallyDeprecated); 62 | XCTAssertTrue(cursor.availability.isUnconditionallyUnavailable); 63 | XCTAssertEqualObjects(cursor.availability.unconditionalDeprecationMessage, @"deprecated"); 64 | XCTAssertEqualObjects(cursor.availability.unconditionalUnavailabilityMessage, @"unavailable"); 65 | XCTAssertTrue([cursor.availability.platformAvailabilityEntries count] == 0); 66 | } 67 | 68 | - (void) testAvailabilityAttribute { 69 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f() __attribute__((availability(macos,introduced=10.4.3,deprecated=10.6,obsoleted=10.7,message=\"message\")));"]; 70 | PLClangCursor *cursor = [tu cursorWithSpelling: @"f"]; 71 | XCTAssertNotNil(cursor); 72 | XCTAssertEqual(cursor.availability.kind, PLClangAvailabilityKindUnavailable); 73 | XCTAssertFalse(cursor.availability.isUnconditionallyDeprecated, @"Cursor should not be unconditionally deprecated"); 74 | XCTAssertFalse(cursor.availability.isUnconditionallyUnavailable, @"Cursor should not be unconditionally unavailable"); 75 | XCTAssertTrue([cursor.availability.platformAvailabilityEntries count] == 1); 76 | 77 | PLClangPlatformAvailability *availability = cursor.availability.platformAvailabilityEntries[0]; 78 | XCTAssertEqualObjects(availability.platformName, @"macos"); 79 | XCTAssertEqualObjects(availability.message, @"message"); 80 | 81 | XCTAssertEqual(availability.introducedVersion.major, 10); 82 | XCTAssertEqual(availability.introducedVersion.minor, 4); 83 | XCTAssertEqual(availability.introducedVersion.patch, 3); 84 | XCTAssertEqualObjects([availability.introducedVersion description], @"10.4.3"); 85 | 86 | XCTAssertEqual(availability.deprecatedVersion.major, 10); 87 | XCTAssertEqual(availability.deprecatedVersion.minor, 6); 88 | XCTAssertEqual(availability.deprecatedVersion.patch, -1); 89 | XCTAssertEqualObjects([availability.deprecatedVersion description], @"10.6"); 90 | 91 | XCTAssertEqual(availability.obsoletedVersion.major, 10); 92 | XCTAssertEqual(availability.obsoletedVersion.minor, 7); 93 | XCTAssertEqual(availability.obsoletedVersion.patch, -1); 94 | XCTAssertEqualObjects([availability.obsoletedVersion description], @"10.7"); 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangComment.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | /** 9 | * The kind of a PLClangComment. 10 | */ 11 | typedef NS_ENUM(NSUInteger, PLClangCommentKind) { 12 | /** Inline text. */ 13 | PLClangCommentKindText = 1, 14 | 15 | /** An inline command with word-like arguments, such as "\@c command". */ 16 | PLClangCommentKindInlineCommand = 2, 17 | 18 | /** An HTML start tag. */ 19 | PLClangCommentKindHTMLStartTag = 3, 20 | 21 | /** An HTML end tag. */ 22 | PLClangCommentKindHTMLEndTag = 4, 23 | 24 | /** A paragraph. */ 25 | PLClangCommentKindParagraph = 5, 26 | 27 | /** 28 | * A command that has zero or more word-like arguments and a paragraph argument. 29 | * 30 | * For example, \@brief has zero word-like arguments and a paragraph argument. 31 | */ 32 | PLClangCommentKindBlockCommand = 6, 33 | 34 | /** A \@param command that describes a parameter. */ 35 | PLClangCommentKindParamCommand = 7, 36 | 37 | /** A \@tparam command that describes a template parameter. */ 38 | PLClangCommentKindTParamCommand = 8, 39 | 40 | /** 41 | * A verbatim block command such as preformatted code. 42 | * 43 | * A verbatim block has opening and closing commands and contains multiple 44 | * lines of text as child nodes. For example: 45 | * 46 | * \@verbatim 47 | * text 48 | * \@endverbatim 49 | */ 50 | PLClangCommentKindVerbatimBlockCommand = 9, 51 | 52 | /** A line of text contained within a verbatim block command. */ 53 | PLClangCommentKindVerbatimBlockLine = 10, 54 | 55 | /** 56 | * A verbatim line command. 57 | * 58 | * A verbatim line has an opening command and a single line of text. 59 | * It does not have a closing command. 60 | */ 61 | PLClangCommentKindVerbatimLine = 11, 62 | 63 | /** A full comment attached to an entity. */ 64 | PLClangCommentKindFullComment = 12 65 | }; 66 | 67 | /** 68 | * A rendering hint for a PLClangComment. 69 | */ 70 | typedef NS_ENUM(NSUInteger, PLClangCommentRenderKind) { 71 | PLClangCommentRenderKindNormal = 1, 72 | PLClangCommentRenderKindBold = 2, 73 | PLClangCommentRenderKindMonospaced = 3, 74 | PLClangCommentRenderKindEmphasized = 4 75 | }; 76 | 77 | @interface PLClangComment : NSObject 78 | 79 | @property(nonatomic, readonly) PLClangCommentKind kind; 80 | @property(nonatomic, readonly) PLClangCommentRenderKind renderKind; 81 | 82 | /** 83 | * The name of an inline or block command, or nil if this comment has no command name. 84 | */ 85 | @property(nonatomic, readonly) NSString *commandName; 86 | 87 | /** 88 | * The arguments for an inline or block command. 89 | */ 90 | @property(nonatomic, readonly) NSArray *arguments; 91 | 92 | /** 93 | * The paragraph comment node for a block command, or nil if this comment does not represent a block command. 94 | */ 95 | @property(nonatomic, readonly) PLClangComment *paragraph; 96 | 97 | /** 98 | * A Boolean value indicating whether the parameter that this comment node represents 99 | * was found in the function or method. 100 | */ 101 | @property(nonatomic, readonly) BOOL isParameterIndexValid; 102 | 103 | /** 104 | * The zero-based index of the parameter in the function or method. 105 | */ 106 | @property(nonatomic, readonly) NSUInteger parameterIndex; 107 | 108 | /** 109 | * The parameter's name, or nil if this comment does not represent a parameter. 110 | */ 111 | @property(nonatomic, readonly) NSString *parameterName; 112 | 113 | /** 114 | * The text content of this comment, or nil if the comment has no text content. 115 | */ 116 | @property(nonatomic, readonly) NSString *text; 117 | 118 | /** 119 | * A Boolean value indicating whether or not this comment contains only whitespace. 120 | */ 121 | @property(nonatomic, readonly) BOOL isWhitespace; 122 | 123 | /** 124 | * The children of this comment node. 125 | */ 126 | @property(nonatomic, readonly) NSArray *children; 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangCommentPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangComment.h" 8 | 9 | #import 10 | #import 11 | 12 | @interface PLClangComment (PackagePrivate) 13 | 14 | - (instancetype) initWithOwner: (id) owner cxComment: (CXComment) comment; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangCursorPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangCursor.h" 8 | 9 | #import 10 | 11 | @interface PLClangCursor (PackagePrivate) 12 | 13 | - (instancetype) initWithOwner: (id) owner cxCursor: (CXCursor) cursor; 14 | - (CXCursor) cxCursor; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangDiagnostic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | typedef NS_ENUM(NSUInteger, PLClangDiagnosticSeverity) { 9 | /** A diagnostic that has been suppressed, eg, by a command line option. */ 10 | PLClangDiagnosticSeverityIgnored = 1, 11 | 12 | /** A diagnostic that indicates suspicious code that may be ill-formed. */ 13 | PLClangDiagnosticSeverityWarning = 2, 14 | 15 | /** A diagnostic that indicates that the code is ill-formed. */ 16 | PLClangDiagnosticSeverityError = 3, 17 | 18 | /** A diagnostic that indicates that the code is ill-formed and any further parser recovery is unlikely to 19 | * produce useful results. */ 20 | PLClangDiagnosticSeverityFatal = 4, 21 | }; 22 | 23 | @interface PLClangDiagnostic : NSObject 24 | 25 | /** The formatted error message, as it would be presented by clang */ 26 | @property(nonatomic, readonly) NSString *formattedErrorMessage; 27 | 28 | /** Diagnostic severity */ 29 | @property(nonatomic, readonly) PLClangDiagnosticSeverity severity; 30 | 31 | /** Child diagnostics, as an ordered array of PLClangDiagnostic instances. */ 32 | @property(nonatomic, readonly) NSArray *childDiagnostics; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangDiagnostic.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangDiagnostic.h" 7 | #import "PLClangDiagnosticPrivate.h" 8 | #import "PLClangNSString.h" 9 | #import "PLAdditions.h" 10 | 11 | /** 12 | * A clang diagnostic message. 13 | */ 14 | @implementation PLClangDiagnostic { 15 | @private 16 | /** Backing clang diagnostic location. */ 17 | CXDiagnostic *_diagnostic; 18 | } 19 | 20 | - (void) dealloc { 21 | if (_diagnostic != NULL) 22 | clang_disposeDiagnostic(_diagnostic); 23 | } 24 | 25 | // property getter 26 | - (NSString *) formattedErrorMessage { 27 | CXString formatted = clang_formatDiagnostic(_diagnostic, clang_defaultDiagnosticDisplayOptions()); 28 | return plclang_convert_and_dispose_cxstring(formatted); 29 | } 30 | 31 | // property getter 32 | - (PLClangDiagnosticSeverity) severity { 33 | switch (clang_getDiagnosticSeverity(_diagnostic)) { 34 | case CXDiagnostic_Ignored: 35 | return PLClangDiagnosticSeverityIgnored; 36 | 37 | case CXDiagnostic_Note: 38 | // XXX unsupported 39 | abort(); 40 | 41 | case CXDiagnostic_Warning: 42 | return PLClangDiagnosticSeverityWarning; 43 | 44 | case CXDiagnostic_Error: 45 | return PLClangDiagnosticSeverityError; 46 | 47 | case CXDiagnostic_Fatal: 48 | return PLClangDiagnosticSeverityFatal; 49 | } 50 | } 51 | 52 | - (NSString *) description { 53 | return self.formattedErrorMessage; 54 | } 55 | 56 | @end 57 | 58 | /** 59 | * @internal 60 | * Package-private methods. 61 | */ 62 | @implementation PLClangDiagnostic (PackagePrivate) 63 | 64 | /** 65 | * Initialize with the given diagnostic. 66 | * 67 | * @param diagnostic Backing clang diagnostic. The receiver will assume ownership over the value. 68 | */ 69 | - (instancetype) initWithCXDiagnostic: (CXDiagnostic) diagnostic { 70 | PLSuperInit(); 71 | 72 | _diagnostic = diagnostic; 73 | 74 | /* Recursively parse child diagnostics */ 75 | CXDiagnosticSet childSet = clang_getChildDiagnostics(_diagnostic); 76 | if (childSet != NULL) { 77 | unsigned int childCount = clang_getNumDiagnosticsInSet(childSet); 78 | NSMutableArray *childDiagnostics = [NSMutableArray arrayWithCapacity: childCount]; 79 | _childDiagnostics = childDiagnostics; 80 | 81 | for (unsigned int i = 0; i < childCount; i++) { 82 | CXDiagnostic childDiagnostic = clang_getDiagnosticInSet(childSet, i); 83 | [childDiagnostics addObject: [[PLClangDiagnostic alloc] initWithCXDiagnostic: childDiagnostic]]; 84 | } 85 | clang_disposeDiagnosticSet(childSet); 86 | } 87 | 88 | return self; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangDiagnosticPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | #import 6 | #import 7 | 8 | #import "PLClangDiagnostic.h" 9 | 10 | @interface PLClangDiagnostic (PackagePrivate) 11 | 12 | - (instancetype) initWithCXDiagnostic: (CXDiagnostic) diagnostic; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangNSString.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | NSString *plclang_convert_cxstring(CXString string); 5 | NSString *plclang_convert_and_dispose_cxstring(CXString string); 6 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangNSString.m: -------------------------------------------------------------------------------- 1 | #import "PLClangNSString.h" 2 | 3 | /** 4 | * Returns an NSString with the contents of the given CXString, or 5 | * nil if given a null CXString. 6 | */ 7 | NSString *plclang_convert_cxstring(CXString string) { 8 | const char *cstring = clang_getCString(string); 9 | return cstring ? [NSString stringWithUTF8String: cstring] : nil; 10 | } 11 | 12 | /** 13 | * Returns an NSString with the contents of the given CXString and 14 | * disposes the CXString. 15 | * 16 | * Returns nil if given a null CXString. 17 | * 18 | * Unless otherwise stated all CXStrings returned from clang must be 19 | * disposed. 20 | */ 21 | NSString *plclang_convert_and_dispose_cxstring(CXString string) { 22 | NSString *result = plclang_convert_cxstring(string); 23 | clang_disposeString(string); 24 | return result; 25 | } 26 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangPlatformAvailability.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangVersion.h" 8 | 9 | @interface PLClangPlatformAvailability : NSObject 10 | 11 | /** 12 | * The name of the platform. 13 | * 14 | * Possible values are "ios" and "macosx". 15 | */ 16 | @property(nonatomic, readonly) NSString *platformName; 17 | 18 | /** 19 | * The version in which the entity was introduced. 20 | */ 21 | @property(nonatomic, readonly) PLClangVersion *introducedVersion; 22 | 23 | /** 24 | * The version in which the entity was deprecated (but is still available). 25 | */ 26 | @property(nonatomic, readonly) PLClangVersion *deprecatedVersion; 27 | 28 | /** 29 | * The version in which the entity was obsoleted, and therefore is no longer available. 30 | */ 31 | @property(nonatomic, readonly) PLClangVersion *obsoletedVersion; 32 | 33 | /** 34 | * An optional message to provide to a user of a deprecated or obsoleted entity, possibly to suggest replacement APIs. 35 | */ 36 | @property(nonatomic, copy) NSString *message; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangPlatformAvailability.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangPlatformAvailability.h" 7 | #import "PLClangPlatformAvailabilityPrivate.h" 8 | #import "PLClangVersionPrivate.h" 9 | #import "PLClangNSString.h" 10 | #import "PLAdditions.h" 11 | 12 | /** 13 | * Platform-specific availability information for an entity. 14 | */ 15 | @implementation PLClangPlatformAvailability 16 | 17 | - (NSString *) description { 18 | NSMutableString *string = [NSMutableString stringWithString: self.platformName]; 19 | 20 | if (self.introducedVersion) { 21 | [string appendFormat: @" introduced: %@", self.introducedVersion]; 22 | } 23 | 24 | if (self.deprecatedVersion) { 25 | [string appendFormat: @" deprecated: %@", self.deprecatedVersion]; 26 | } 27 | 28 | if (self.obsoletedVersion) { 29 | [string appendFormat: @" obsoleted: %@", self.obsoletedVersion]; 30 | } 31 | 32 | if ([self.message length] > 0) { 33 | [string appendFormat: @" \"%@\"", self.message]; 34 | } 35 | 36 | return string; 37 | } 38 | 39 | @end 40 | 41 | /** 42 | * @internal 43 | * Package-private methods. 44 | */ 45 | @implementation PLClangPlatformAvailability (PackagePrivate) 46 | 47 | /** 48 | * Initialize a newly-created platform availability instance with the specified clang platform availability information. 49 | * 50 | * @param availability The clang availability structure that will provide platform availability information. 51 | * @return An initialized availability instance. 52 | */ 53 | - (instancetype) initWithCXPlatformAvailability: (CXPlatformAvailability) availability { 54 | PLSuperInit(); 55 | 56 | // The strings in CXPlatformAvailability are disposed via clang_disposeCXPlatformAvailability(), just convert them 57 | _platformName = plclang_convert_cxstring(availability.Platform); 58 | _message = plclang_convert_cxstring(availability.Message); 59 | _introducedVersion = [[PLClangVersion alloc] initWithCXVersion: availability.Introduced]; 60 | _deprecatedVersion = [[PLClangVersion alloc] initWithCXVersion: availability.Deprecated]; 61 | _obsoletedVersion = [[PLClangVersion alloc] initWithCXVersion: availability.Obsoleted]; 62 | 63 | return self; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangPlatformAvailabilityPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangPlatformAvailability.h" 8 | 9 | #import 10 | 11 | @interface PLClangPlatformAvailability (PackagePrivate) 12 | 13 | - (instancetype) initWithCXPlatformAvailability: (CXPlatformAvailability) availability; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceIndex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | #import "PLClangTranslationUnit.h" 9 | #import "PLClangUnsavedFile.h" 10 | 11 | /** 12 | * Options used when creating an index. 13 | */ 14 | typedef NS_OPTIONS(NSUInteger, PLClangIndexCreationOptions) { 15 | /** 16 | * Specifies that the index should only allow enumeration of "local" 17 | * declarations when loading new translation units. A "local" declaration 18 | * is one that belongs in the translation unit itself and not in a precompiled 19 | * header. 20 | */ 21 | PLClangIndexCreationExcludePCHDeclarations = 1UL << 0, 22 | 23 | /** 24 | * Specifies that diagnostics should be output to the console when parsing 25 | * translation units. 26 | */ 27 | PLClangIndexCreationDisplayDiagnostics = 1UL << 1 28 | }; 29 | 30 | /** 31 | * Options used when creating a translation unit. 32 | */ 33 | typedef NS_OPTIONS(NSUInteger, PLClangTranslationUnitCreationOptions) { 34 | /** 35 | * Specifies that the parser should construct a detailed preprocessing 36 | * record that includes all macro definitions and instantiations. 37 | * 38 | * Constructing a detailed preprocessing record requires more memory 39 | * and time to parse since the information contained in the record 40 | * is usually not retained. However, it can be useful for 41 | * applications that require more detailed information about the 42 | * behavior of the preprocessor. 43 | */ 44 | PLClangTranslationUnitCreationDetailedPreprocessingRecord = 1UL << 0, 45 | 46 | /** 47 | * Specifies that the translation unit is incomplete. 48 | * 49 | * When a translation unit is considered incomplete semantic analysis that 50 | * is typically performed at the end of the translation unit will be 51 | * suppressed. For example, this suppresses the completion of tentative 52 | * declarations in C and of instantiation of implicitly-instantiated function 53 | * templates in C++. This option is typically used when parsing a header with 54 | * the intent of producing a precompiled header. 55 | */ 56 | PLClangTranslationUnitCreationIncomplete = 1UL << 1, 57 | 58 | /** 59 | * Specifies that the translation unit should be built with an implicit 60 | * precompiled header for the preamble. 61 | * 62 | * An implicit precompiled header can be used as an optimization when a 63 | * particular translation unit is likely to be reparsed many times and the 64 | * sources aren't changing that often. In this case, an implicit precompiled 65 | * header will be built containing all of the initial includes at the top of 66 | * the main file (the "preamble" of the file). In subsequent parses, if the 67 | * preamble or the files in it have not changed, reparsing the translation 68 | * unit will re-use the implicit precompiled header to improve parsing 69 | * performance. 70 | */ 71 | PLClangTranslationUnitCreationPrecompilePreamble = 1UL << 2, 72 | 73 | /** 74 | * Specifies that the translation unit should cache some code-completion 75 | * results with each reparse of the source file. 76 | * 77 | * Caching of code-completion results is a performance optimization that 78 | * introduces some overhead to reparsing but improves the performance of 79 | * code-completion operations. 80 | */ 81 | PLClangTranslationUnitCreationCacheCodeCompletionResults = 1UL << 3, 82 | 83 | /** 84 | * Specifies that the translation unit will later be saved to disk. 85 | * 86 | * This option is typically used when parsing a header with the intent of 87 | * producing a precompiled header. 88 | */ 89 | PLClangTranslationUnitCreationForSerialization = 1UL << 4, 90 | 91 | /** 92 | * Specifies that function and method bodies should be skipped while parsing. 93 | * 94 | * This option can be used to improve parsing performance when the translation 95 | * unit will only be searched for declarations/definitions while ignoring the 96 | * usages. 97 | */ 98 | PLClangTranslationUnitCreationSkipFunctionBodies = 1UL << 5, 99 | 100 | /** 101 | * Specifies that brief documentation comments should be included in the set 102 | * of code completions returned from a translation unit. 103 | */ 104 | PLClangTranslationUnitCreationIncludeBriefCommentsInCodeCompletion = 1UL << 6 105 | }; 106 | 107 | @interface PLClangSourceIndex : NSObject 108 | 109 | + (instancetype) indexWithOptions: (PLClangIndexCreationOptions) options; 110 | 111 | - (PLClangTranslationUnit *) addTranslationUnitWithASTPath: (NSString *) path 112 | error: (NSError **) error; 113 | 114 | - (PLClangTranslationUnit *) addTranslationUnitWithSourcePath: (NSString *) path 115 | unsavedFiles: (NSArray *) files 116 | compilerArguments: (NSArray *) arguments 117 | options: (PLClangTranslationUnitCreationOptions) options 118 | error: (NSError **) error; 119 | 120 | - (PLClangTranslationUnit *) addTranslationUnitWithSourcePath: (NSString *) path 121 | fileData: (NSData *) data 122 | compilerArguments: (NSArray *) arguments 123 | options: (PLClangTranslationUnitCreationOptions) options 124 | error: (NSError **) error; 125 | 126 | - (PLClangTranslationUnit *) addTranslationUnitWithCompilerArguments: (NSArray *) arguments 127 | options: (PLClangTranslationUnitCreationOptions) options 128 | error: (NSError **) error; 129 | 130 | - (PLClangTranslationUnit *) addTranslationUnitWithSourcePath: (NSString *) path 131 | compilerArguments: (NSArray *) arguments 132 | options: (PLClangTranslationUnitCreationOptions) options 133 | error: (NSError **) error; 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceIndexTests.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangSourceIndex.h" 8 | #import "PLClang.h" 9 | 10 | @interface PLClangSourceIndexTests : XCTestCase @end 11 | 12 | @implementation PLClangSourceIndexTests { 13 | @private 14 | } 15 | 16 | - (void) testClangVersion { 17 | XCTAssertTrue([PLClangGetVersionString() length] > 0, @"A non-empty string should be returned for the clang version"); 18 | } 19 | 20 | - (void) testAddTranslationUnitWithSourcePath { 21 | NSError *error = nil; 22 | NSData *test = [@"int main (int argc, char *argv[]) { return 0; }" dataUsingEncoding: NSUTF8StringEncoding]; 23 | PLClangSourceIndex *idx = [PLClangSourceIndex new]; 24 | PLClangTranslationUnit *tu = [idx addTranslationUnitWithSourcePath: @"test.c" fileData: test compilerArguments: @[] options: 0 error: &error]; 25 | XCTAssertNotNil(tu, @"Failed to parse", nil); 26 | XCTAssertNil(error, @"Received error for successful parse"); 27 | } 28 | 29 | - (void) testAddTranslationUnitWithMultipleUnsavedFiles { 30 | NSError *error = nil; 31 | NSData *header = [@"int f();" dataUsingEncoding: NSUTF8StringEncoding]; 32 | NSData *source = [@"#include \"test.h\"\nint f () { return 0; }" dataUsingEncoding: NSUTF8StringEncoding]; 33 | 34 | // Absolute paths are needed for clang to be able to resolve the include directive 35 | 36 | NSArray *files = @[ 37 | [PLClangUnsavedFile unsavedFileWithPath: @"/tmp/test.h" data: header], 38 | [PLClangUnsavedFile unsavedFileWithPath: @"/tmp/test.c" data: source] 39 | ]; 40 | 41 | PLClangSourceIndex *idx = [PLClangSourceIndex new]; 42 | PLClangTranslationUnit *tu = [idx addTranslationUnitWithSourcePath: @"/tmp/test.c" unsavedFiles: files compilerArguments: @[] options: 0 error: &error]; 43 | XCTAssertNotNil(tu, @"Failed to parse", nil); 44 | XCTAssertNil(error, @"Received error for successful parse"); 45 | 46 | XCTAssertFalse(tu.didFail, @"Should be marked as non-failed: %@", tu.diagnostics); 47 | XCTAssertTrue([tu.diagnostics count] == 0, @"No diagnostics should be returned"); 48 | } 49 | 50 | - (void) testFailedTranslationUnitCreation { 51 | NSError *error = nil; 52 | PLClangSourceIndex *idx = [PLClangSourceIndex new]; 53 | PLClangTranslationUnit *tu = [idx addTranslationUnitWithSourcePath: @"notfound.c" fileData: nil compilerArguments: @[] options: 0 error: &error]; 54 | XCTAssertNil(tu, @"Received a translation unit for a file that should not exist", nil); 55 | XCTAssertNotNil(error, @"No error received for failed parse"); 56 | XCTAssertEqual(error.code, PLClangErrorCompiler); 57 | 58 | tu = [idx addTranslationUnitWithSourcePath: @"notfound.c" compilerArguments: @[] options: 0 error: &error]; 59 | XCTAssertNil(tu, @"Received a translation unit for a file that should not exist", nil); 60 | XCTAssertNotNil(error, @"No error received for failed parse"); 61 | XCTAssertEqual(error.code, PLClangErrorCompiler); 62 | 63 | tu = [idx addTranslationUnitWithASTPath: @"notfound.pch" error: &error]; 64 | XCTAssertNil(tu, @"Received a translation unit for a file that should not exist", nil); 65 | XCTAssertNotNil(error, @"No error received for failed parse"); 66 | XCTAssertEqual(error.code, PLClangErrorCompiler); 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceLocation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | @class PLClangTranslationUnit; 8 | 9 | @interface PLClangSourceLocation : NSObject 10 | 11 | - (instancetype) initWithTranslationUnit: (PLClangTranslationUnit *) translationUnit 12 | file: (NSString *) path 13 | offset: (off_t) offset; 14 | 15 | - (instancetype) initWithTranslationUnit: (PLClangTranslationUnit *) translationUnit 16 | file: (NSString *) path 17 | lineNumber: (NSUInteger) lineNumber 18 | columnNumber: (NSUInteger) columnNumber; 19 | 20 | /** 21 | * The path of the file containing this source location. 22 | */ 23 | @property(nonatomic, readonly) NSString *path; 24 | 25 | /** 26 | * The byte offset within the file. 27 | */ 28 | @property(nonatomic, readonly) off_t fileOffset; 29 | 30 | /** 31 | * The line number within the file (1-based). 32 | */ 33 | @property(nonatomic, readonly) NSUInteger lineNumber; 34 | 35 | /** 36 | * The column number within the file (1-based). 37 | */ 38 | @property(nonatomic, readonly) NSUInteger columnNumber; 39 | 40 | /** 41 | * A Boolean value indicating whether the location is within the main file of the translation unit. 42 | */ 43 | @property(nonatomic, readonly) BOOL isInMainFile; 44 | 45 | /** 46 | * A Boolean value indicating whether the location is within a system header. 47 | */ 48 | @property(nonatomic, readonly) BOOL isInSystemHeader; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceLocation.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangSourceLocation.h" 7 | #import "PLClangSourceLocationPrivate.h" 8 | #import "PLClangTranslationUnitPrivate.h" 9 | #import "PLClangNSString.h" 10 | #import "PLAdditions.h" 11 | 12 | /** 13 | * A clang source location within a translation unit. 14 | */ 15 | @implementation PLClangSourceLocation { 16 | @private 17 | /** The owner of the clang data structure backing _location. This is used 18 | * to ensure the lifetime of the CXSourceLocation. */ 19 | id _owner; 20 | 21 | /** Backing clang source location. */ 22 | CXSourceLocation _location; 23 | 24 | /** 25 | * Indicates whether or not the expansion location has been read from the 26 | * source location. 27 | * 28 | * Obtaining the expansion location is an expensive operation, so it is 29 | * deferred until a property that requires it is read. 30 | */ 31 | BOOL _expansionLocationRead; 32 | 33 | /** The path to the file. */ 34 | NSString *_path; 35 | 36 | /** The byte offset within the file. */ 37 | off_t _fileOffset; 38 | 39 | /** The line number within the file. */ 40 | NSUInteger _lineNumber; 41 | 42 | /** The column number within the file. */ 43 | NSUInteger _columnNumber; 44 | } 45 | 46 | /** 47 | * Initialize a newly-created source range with the specified translation unit, and offset within a source file. 48 | * 49 | * @param translationUnit The translation unit containing the source location. 50 | * @param path Path to the source file containing the source location. 51 | * @param offset Byte offset within the source file. 52 | * @return An initialized source location or nil if the requested location is invalid. 53 | * 54 | * @internal 55 | * clang's behavior in handling a request for a source location beyond the range of the source file is 56 | * inconsistent. If given a file offset beyond the file's range it will return a garbage location. If 57 | * given a line or column number beyond the file's range it will return the closest source location within 58 | * the file. To be consistent in this API, check that the resulting source location is what was requested 59 | * and return nil if not. 60 | */ 61 | - (instancetype) initWithTranslationUnit: (PLClangTranslationUnit *) translationUnit file: (NSString *) path offset: (off_t) offset { 62 | if (!translationUnit || !path) 63 | return nil; 64 | 65 | CXFile file = clang_getFile([translationUnit cxTranslationUnit], [path fileSystemRepresentation]); 66 | if (!file) 67 | return nil; 68 | 69 | CXSourceLocation sourceLocation = clang_getLocationForOffset([translationUnit cxTranslationUnit], file, (unsigned int)offset); 70 | PLClangSourceLocation *location = [self initWithOwner: translationUnit cxSourceLocation: sourceLocation]; 71 | if (location != nil && location.fileOffset != offset) 72 | return nil; 73 | 74 | return location; 75 | } 76 | 77 | /** 78 | * Initialize a newly-created source range with the specified translation unit, and line and column numbers within a source file. 79 | * 80 | * @param translationUnit The translation unit containing the source location. 81 | * @param path Path to the source file containing the source location. 82 | * @param lineNumber 1-based line number within the source file containing. 83 | * @param columnNumber 1-based column number within the source file. 84 | * @return An initialized source location or nil if the requested location is invalid. 85 | * 86 | * @internal 87 | * clang's behavior in handling a request for a source location beyond the range of the source file is 88 | * inconsistent. If given a file offset beyond the file's range it will return a garbage location. If 89 | * given a line or column number beyond the file's range it will return the closest source location within 90 | * the file. To be consistent in this API, check that the resulting source location is what was requested 91 | * and return nil if not. 92 | */ 93 | - (instancetype) initWithTranslationUnit: (PLClangTranslationUnit *) translationUnit file: (NSString *) path lineNumber: (NSUInteger) lineNumber columnNumber: (NSUInteger) columnNumber { 94 | if (!translationUnit || !path) 95 | return nil; 96 | 97 | CXFile file = clang_getFile([translationUnit cxTranslationUnit], [path fileSystemRepresentation]); 98 | if (!file) 99 | return nil; 100 | 101 | CXSourceLocation sourceLocation = clang_getLocation([translationUnit cxTranslationUnit], file, (unsigned int)lineNumber, (unsigned int)columnNumber); 102 | PLClangSourceLocation *location = [self initWithOwner: translationUnit cxSourceLocation: sourceLocation]; 103 | if (location != nil && (location.lineNumber != lineNumber || location.columnNumber != columnNumber)) 104 | return nil; 105 | 106 | return location; 107 | } 108 | 109 | - (NSString *) path { 110 | if (_expansionLocationRead == NO) { 111 | [self readExpansionLocation]; 112 | } 113 | 114 | return _path; 115 | } 116 | 117 | - (off_t) fileOffset { 118 | if (_expansionLocationRead == NO) { 119 | [self readExpansionLocation]; 120 | } 121 | 122 | return _fileOffset; 123 | } 124 | 125 | - (NSUInteger) lineNumber { 126 | if (_expansionLocationRead == NO) { 127 | [self readExpansionLocation]; 128 | } 129 | 130 | return _lineNumber; 131 | } 132 | 133 | - (NSUInteger) columnNumber { 134 | if (_expansionLocationRead == NO) { 135 | [self readExpansionLocation]; 136 | } 137 | 138 | return _columnNumber; 139 | } 140 | 141 | - (BOOL) isInMainFile { 142 | return clang_Location_isFromMainFile(_location); 143 | } 144 | 145 | - (BOOL) isInSystemHeader { 146 | return clang_Location_isInSystemHeader(_location); 147 | } 148 | 149 | - (BOOL) isEqual: (id) object { 150 | if (![object isKindOfClass: [PLClangSourceLocation class]]) 151 | return NO; 152 | 153 | return clang_equalLocations(_location, [object cxSourceLocation]); 154 | } 155 | 156 | /** 157 | * @internal 158 | * Clang should provide a function for this similar to clang_hashCursor(). 159 | * For now this is based on the implementation of clang_equalLocations(), which 160 | * checks for equality of the data pointers. 161 | */ 162 | - (NSUInteger) hash { 163 | return (NSUInteger)_location.ptr_data[0] ^ (NSUInteger)_location.ptr_data[1] ^ _location.int_data; 164 | } 165 | 166 | - (NSString *) description { 167 | return [NSString stringWithFormat: @"%@:%lu:%lu", 168 | self.path, 169 | (unsigned long)self.lineNumber, 170 | (unsigned long)self.columnNumber]; 171 | } 172 | 173 | - (void) readExpansionLocation { 174 | CXFile file = NULL; 175 | unsigned int line = 0, column = 0, offset = 0; 176 | clang_getExpansionLocation(_location, &file, &line, &column, &offset); 177 | 178 | _path = plclang_convert_and_dispose_cxstring(clang_getFileName(file)); 179 | _fileOffset = offset; 180 | _lineNumber = line; 181 | _columnNumber = column; 182 | 183 | _expansionLocationRead = YES; 184 | } 185 | 186 | @end 187 | 188 | /** 189 | * @internal 190 | * Package-private methods. 191 | */ 192 | @implementation PLClangSourceLocation (PackagePrivate) 193 | 194 | /** 195 | * Initialize with the source location 196 | * 197 | * @param owner An Objective-C reference to the owner of the sourceLocation value. This reference will 198 | * be retained, as to ensure that @a sourceLocation survives for the lifetime of the source location instance. 199 | * @param sourceLocation Backing clang location. 200 | * @return An initialized source location or nil if a null clang source location was provided. 201 | */ 202 | - (instancetype) initWithOwner: (id) owner cxSourceLocation: (CXSourceLocation) sourceLocation { 203 | PLSuperInit(); 204 | 205 | if (clang_equalLocations(sourceLocation, clang_getNullLocation())) 206 | return nil; 207 | 208 | _owner = owner; 209 | _location = sourceLocation; 210 | 211 | return self; 212 | } 213 | 214 | - (CXSourceLocation) cxSourceLocation { 215 | return _location; 216 | } 217 | 218 | @end 219 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceLocationPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | #import 6 | #import 7 | 8 | #import "PLClangSourceLocation.h" 9 | 10 | @interface PLClangSourceLocation (PackagePrivate) 11 | 12 | - (instancetype) initWithOwner: (id) owner cxSourceLocation: (CXSourceLocation) sourceLocation; 13 | - (CXSourceLocation) cxSourceLocation; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceRange.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangSourceLocation.h" 8 | 9 | @interface PLClangSourceRange : NSObject 10 | 11 | - (instancetype) initWithStartLocation: (PLClangSourceLocation *) startLocation 12 | endLocation: (PLClangSourceLocation *) endLocation; 13 | 14 | /** 15 | * The start location of this source range. 16 | */ 17 | @property(nonatomic, readonly) PLClangSourceLocation *startLocation; 18 | 19 | /** 20 | * The end location of the this range. 21 | */ 22 | @property(nonatomic, readonly) PLClangSourceLocation *endLocation; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceRange.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangSourceRange.h" 7 | #import "PLClangSourceLocationPrivate.h" 8 | #import "PLAdditions.h" 9 | 10 | /** 11 | * A source range within a translation unit. 12 | */ 13 | @implementation PLClangSourceRange 14 | 15 | /** 16 | * Initialize a newly-created source range with the specified start and end locations. 17 | * 18 | * @param startLocation The source location to mark the start of the range. 19 | * @param endLocation The source location to mark the end of the range. 20 | * @return An initialized source range or nil if the start or end locations were invalid. 21 | */ 22 | - (instancetype) initWithStartLocation: (PLClangSourceLocation *) startLocation endLocation: (PLClangSourceLocation *) endLocation { 23 | PLSuperInit(); 24 | 25 | if (startLocation == nil || endLocation == nil) 26 | return nil; 27 | 28 | _startLocation = startLocation; 29 | _endLocation = endLocation; 30 | 31 | return self; 32 | } 33 | 34 | - (BOOL) isEqual: (id) object { 35 | if (![object isKindOfClass: [PLClangSourceRange class]]) 36 | return NO; 37 | 38 | return [self.startLocation isEqual: [object startLocation]] && 39 | [self.endLocation isEqual: [object endLocation]]; 40 | } 41 | 42 | - (NSUInteger) hash { 43 | return [self.startLocation hash] ^ [self.endLocation hash]; 44 | } 45 | 46 | - (NSString *) description { 47 | return [NSString stringWithFormat: @"{ %@, %@ }", 48 | self.startLocation, 49 | self.endLocation]; 50 | } 51 | 52 | @end 53 | 54 | /** 55 | * @internal 56 | * Package-private methods. 57 | */ 58 | @implementation PLClangSourceRange (PackagePrivate) 59 | 60 | /** 61 | * Initialize a newly-created source range with the specified clang source range. 62 | * 63 | * @param owner A reference to the owner of the clang source range. This reference will be retained 64 | * to ensure that the clang source range survives for the lifetime of this source range instance. 65 | * @param sourceRange The clang source range that will back this object. 66 | * @return An initialized source range or nil if a null clang source range was provided. 67 | */ 68 | - (instancetype) initWithOwner: (id) owner cxSourceRange: (CXSourceRange) sourceRange { 69 | if (clang_Range_isNull(sourceRange)) 70 | return nil; 71 | 72 | PLClangSourceLocation* startLocation = [[PLClangSourceLocation alloc] initWithOwner: owner cxSourceLocation: clang_getRangeStart(sourceRange)]; 73 | PLClangSourceLocation* endLocation = [[PLClangSourceLocation alloc] initWithOwner: owner cxSourceLocation: clang_getRangeEnd(sourceRange)]; 74 | 75 | return [self initWithStartLocation: startLocation endLocation: endLocation]; 76 | } 77 | 78 | - (CXSourceRange) cxSourceRange { 79 | return clang_getRange([self.startLocation cxSourceLocation], [self.endLocation cxSourceLocation]); 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceRangePrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangSourceRange.h" 8 | 9 | #import 10 | 11 | @interface PLClangSourceRange (PackagePrivate) 12 | 13 | - (instancetype) initWithOwner: (id) owner cxSourceRange: (CXSourceRange) sourceRange; 14 | - (CXSourceRange) cxSourceRange; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangSourceRangeTests.m: -------------------------------------------------------------------------------- 1 | #import "PLClangTestCase.h" 2 | 3 | @interface PLClangSourceRangeTests : PLClangTestCase 4 | @end 5 | 6 | @implementation PLClangSourceRangeTests 7 | 8 | - (void) testRange { 9 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t;" path: @"test.c"]; 10 | PLClangSourceRange *range = [[tu cursorWithSpelling: @"t"] extent]; 11 | XCTAssertNotNil(range, @"Cursor should have an extent"); 12 | XCTAssertNotNil(range.startLocation); 13 | XCTAssertNotNil(range.endLocation); 14 | 15 | XCTAssertEqualObjects(range.startLocation.path, @"test.c"); 16 | XCTAssertEqual(range.startLocation.fileOffset, (off_t)0); 17 | XCTAssertEqual(range.startLocation.lineNumber, (NSUInteger)1); 18 | XCTAssertEqual(range.startLocation.columnNumber, (NSUInteger)1); 19 | 20 | XCTAssertEqualObjects(range.endLocation.path, @"test.c"); 21 | XCTAssertEqual(range.endLocation.fileOffset, (off_t)5); 22 | XCTAssertEqual(range.endLocation.lineNumber, (NSUInteger)1); 23 | XCTAssertEqual(range.endLocation.columnNumber, (NSUInteger)6); 24 | } 25 | 26 | - (void) testEquality { 27 | PLClangSourceLocation *location1, *location2; 28 | PLClangSourceRange *range1, *range2; 29 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t;" path: @"test.c"]; 30 | location1 = [[PLClangSourceLocation alloc] initWithTranslationUnit: tu 31 | file: @"test.c" 32 | offset: 0]; 33 | location2 = [[PLClangSourceLocation alloc] initWithTranslationUnit: tu 34 | file: @"test.c" 35 | offset: 1]; 36 | XCTAssertNotNil(location1, @"Failed to create location"); 37 | XCTAssertNotNil(location2, @"Failed to create location"); 38 | 39 | range1 = [[PLClangSourceRange alloc] initWithStartLocation: location1 endLocation: location2]; 40 | 41 | location1 = [[PLClangSourceLocation alloc] initWithTranslationUnit: tu 42 | file: @"test.c" 43 | offset: 0]; 44 | location2 = [[PLClangSourceLocation alloc] initWithTranslationUnit: tu 45 | file: @"test.c" 46 | offset: 1]; 47 | XCTAssertNotNil(location1, @"Failed to create location"); 48 | XCTAssertNotNil(location2, @"Failed to create location"); 49 | 50 | range2 = [[PLClangSourceRange alloc] initWithStartLocation: location1 endLocation: location2]; 51 | XCTAssertEqualObjects(range1, range2, @"Ranges should be equal"); 52 | 53 | location2 = [[PLClangSourceLocation alloc] initWithTranslationUnit: tu 54 | file: @"test.c" 55 | offset: 0]; 56 | XCTAssertNotNil(location2, @"Failed to create location"); 57 | 58 | range2 = [[PLClangSourceRange alloc] initWithStartLocation: location1 endLocation: location2]; 59 | XCTAssertFalse([range1 isEqual: range2], @"Ranges should not be equal"); 60 | } 61 | 62 | - (void) testInvalidRange { 63 | PLClangSourceRange *range; 64 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t;" path: @"test.c"]; 65 | PLClangSourceLocation *location = [[PLClangSourceLocation alloc] initWithTranslationUnit: tu 66 | file: @"test.c" 67 | offset: 0]; 68 | 69 | range = [[PLClangSourceRange alloc] initWithStartLocation: nil endLocation: nil]; 70 | XCTAssertNil(range); 71 | 72 | range = [[PLClangSourceRange alloc] initWithStartLocation: location endLocation: nil]; 73 | XCTAssertNil(range); 74 | 75 | range = [[PLClangSourceRange alloc] initWithStartLocation: nil endLocation: location]; 76 | XCTAssertNil(range); 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTestCase.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "PLClang.h" 3 | 4 | @interface PLClangTestCase : XCTestCase { 5 | PLClangSourceIndex *_index; 6 | } 7 | 8 | - (PLClangTranslationUnit *) translationUnitWithSource: (NSString *) source; 9 | 10 | - (PLClangTranslationUnit *) translationUnitWithSource: (NSString *) source 11 | path: (NSString *) path; 12 | 13 | - (PLClangTranslationUnit *) translationUnitWithSource: (NSString *) source 14 | path: (NSString *) path 15 | options: (PLClangTranslationUnitCreationOptions) options; 16 | 17 | @end 18 | 19 | @interface PLClangTranslationUnit (TestingAdditions) 20 | 21 | - (PLClangCursor *) cursorWithSpelling: (NSString *) spelling; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTestCase.m: -------------------------------------------------------------------------------- 1 | #import "PLClangTestCase.h" 2 | 3 | #define STRINGIFY(x) STRINGIFY_(x) 4 | #define STRINGIFY_(x) @#x 5 | 6 | @implementation PLClangTestCase 7 | 8 | - (void) setUp { 9 | [super setUp]; 10 | _index = [[PLClangSourceIndex alloc] init]; 11 | } 12 | 13 | /** 14 | * Convenience method to create a translation unit from the given source with options 15 | * suitable for typical unit testing. 16 | */ 17 | - (PLClangTranslationUnit *) translationUnitWithSource: (NSString *) source { 18 | return [self translationUnitWithSource: source path: @"test.m"]; 19 | } 20 | 21 | /** 22 | * Convenience method to create a translation unit from the given source and path with 23 | * options suitable for typical unit testing. 24 | */ 25 | - (PLClangTranslationUnit *) translationUnitWithSource: (NSString *) source path: (NSString *) path { 26 | return [self translationUnitWithSource: source path: path options: 0]; 27 | } 28 | 29 | /** 30 | * Convenience method to create a translation unit from the given source and path and options 31 | */ 32 | - (PLClangTranslationUnit *) translationUnitWithSource: (NSString *) source path: (NSString *) path options: (PLClangTranslationUnitCreationOptions) options { 33 | NSError *error = nil; 34 | NSData *data = [source dataUsingEncoding: NSUTF8StringEncoding]; 35 | PLClangUnsavedFile *file = [PLClangUnsavedFile unsavedFileWithPath: path data: data]; 36 | PLClangTranslationUnit *tu = [_index addTranslationUnitWithSourcePath: path 37 | unsavedFiles: @[file] 38 | compilerArguments: @[@"-isysroot", STRINGIFY(SDKROOT)] 39 | options: options 40 | error: &error]; 41 | XCTAssertNotNil(tu, @"Failed to parse", nil); 42 | XCTAssertNil(error, @"Received error for successful parse"); 43 | XCTAssertFalse(tu.didFail, @"Should be marked as non-failed: %@", tu.diagnostics); 44 | 45 | return tu; 46 | } 47 | 48 | @end 49 | 50 | @implementation PLClangTranslationUnit (TestingAdditions) 51 | 52 | /** 53 | * Returns the first cursor in the translation unit with the specified spelling 54 | */ 55 | - (PLClangCursor *) cursorWithSpelling: (NSString *) spelling { 56 | __block PLClangCursor *cursor = nil; 57 | [self.cursor visitChildrenUsingBlock: ^PLClangCursorVisitResult(PLClangCursor *child) { 58 | if ([child.spelling isEqualToString: spelling]) { 59 | cursor = child; 60 | return PLClangCursorVisitBreak; 61 | } 62 | return PLClangCursorVisitRecurse; 63 | }]; 64 | 65 | return cursor; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangToken.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangCursor.h" 8 | 9 | /** 10 | * The kind of a PLClangToken. 11 | */ 12 | typedef NS_ENUM(NSUInteger, PLClangTokenKind) { 13 | /** A token that contains some kind of punctuation. */ 14 | PLClangTokenKindPunctuation, 15 | 16 | /** A language keyword. */ 17 | PLClangTokenKindKeyword, 18 | 19 | /** An identifier (that is not a keyword). */ 20 | PLClangTokenKindIdentifier, 21 | 22 | /** A numeric, string, or character literal. */ 23 | PLClangTokenKindLiteral, 24 | 25 | /** A comment. */ 26 | PLClangTokenKindComment 27 | }; 28 | 29 | @interface PLClangToken : NSObject 30 | 31 | /** 32 | * The token's kind. 33 | */ 34 | @property(nonatomic, readonly) PLClangTokenKind kind; 35 | 36 | /** 37 | * A string representation of the token. 38 | */ 39 | @property(nonatomic, readonly) NSString *spelling; 40 | 41 | /** 42 | * The token's source location. 43 | */ 44 | @property(nonatomic, readonly) PLClangSourceLocation *location; 45 | 46 | /** 47 | * The source range covering this token. 48 | */ 49 | @property(nonatomic, readonly) PLClangSourceRange *extent; 50 | 51 | /** 52 | * The cursor for the token, or nil if it cannot be mapped to a specific entity within the abstract syntax tree. 53 | */ 54 | @property(nonatomic, readonly) PLClangCursor *cursor; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangToken.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangToken.h" 7 | #import "PLClangTokenPrivate.h" 8 | #import "PLClangSourceLocationPrivate.h" 9 | #import "PLClangSourceRangePrivate.h" 10 | #import "PLClangTranslationUnitPrivate.h" 11 | #import "PLClangNSString.h" 12 | #import "PLAdditions.h" 13 | 14 | /** 15 | * A preprocessing token. 16 | */ 17 | @implementation PLClangToken { 18 | /** 19 | * A reference to the owning object (the token set), held so that the 20 | * CXToken remains valid for the lifetime of the token. 21 | */ 22 | id _owner; 23 | 24 | /** The backing clang token. */ 25 | CXToken _token; 26 | 27 | /** 28 | * The translation unit in which this token resides, used to access 29 | * token attributes. 30 | */ 31 | PLClangTranslationUnit *_tu; 32 | 33 | /** The source location for this token. */ 34 | PLClangSourceLocation *_location; 35 | 36 | /** The source range for the extent of this token. */ 37 | PLClangSourceRange *_extent; 38 | } 39 | 40 | - (PLClangTokenKind) kind { 41 | switch (clang_getTokenKind(_token)) { 42 | case CXToken_Punctuation: 43 | return PLClangTokenKindPunctuation; 44 | 45 | case CXToken_Keyword: 46 | return PLClangTokenKindKeyword; 47 | 48 | case CXToken_Identifier: 49 | return PLClangTokenKindIdentifier; 50 | 51 | case CXToken_Literal: 52 | return PLClangTokenKindLiteral; 53 | 54 | case CXToken_Comment: 55 | return PLClangTokenKindComment; 56 | } 57 | 58 | // Token has an unknown kind 59 | abort(); 60 | } 61 | 62 | - (PLClangSourceLocation *) location { 63 | return _location ?: (_location = [[PLClangSourceLocation alloc] initWithOwner: _tu cxSourceLocation: clang_getTokenLocation([_tu cxTranslationUnit], _token)]); 64 | } 65 | 66 | - (PLClangSourceRange *) extent { 67 | return _extent ?: (_extent = [[PLClangSourceRange alloc] initWithOwner: _tu cxSourceRange: clang_getTokenExtent([_tu cxTranslationUnit], _token)]); 68 | } 69 | 70 | - (NSString *) description { 71 | return self.spelling; 72 | } 73 | 74 | - (NSString *) debugDescription { 75 | return [NSString stringWithFormat: @"<%@: %p> %@", [self class], self, [self description]]; 76 | } 77 | 78 | @end 79 | 80 | /** 81 | * @internal 82 | * Package-private methods. 83 | */ 84 | @implementation PLClangToken (PackagePrivate) 85 | 86 | /** 87 | * Initialize a newly-created token with the specified clang token. 88 | * 89 | * @param owner A reference to the owner of the clang token. This reference will be retained 90 | * to ensure that the clang token survives for the lifetime of this instance. 91 | * @param translationUnit The translation in which this token resides. 92 | * @param cursor The cursor associated with this token, or nil if there is no associated cursor. 93 | * @param token The clang token that will back this object. 94 | * @return An initialized token. 95 | */ 96 | - (instancetype) initWithOwner: (id) owner translationUnit: (PLClangTranslationUnit *) translationUnit cursor: (PLClangCursor *) cursor cxToken: (CXToken) token { 97 | PLSuperInit(); 98 | 99 | _owner = owner; 100 | _tu = translationUnit; 101 | _token = token; 102 | _cursor = cursor; 103 | _spelling = plclang_convert_and_dispose_cxstring(clang_getTokenSpelling([_tu cxTranslationUnit], _token)); 104 | 105 | return self; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTokenPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangToken.h" 8 | @class PLClangCursor; 9 | @class PLClangTranslationUnit; 10 | 11 | #import 12 | 13 | @interface PLClangToken (PackagePrivate) 14 | 15 | - (instancetype) initWithOwner: (id) owner 16 | translationUnit: (PLClangTranslationUnit *) translationUnit 17 | cursor: (PLClangCursor *) cursor 18 | cxToken: (CXToken) token; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTokenSet.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | @class PLClangTranslationUnit; 4 | 5 | @interface PLClangTokenSet : NSObject 6 | 7 | - (instancetype) initWithTranslationUnit: (PLClangTranslationUnit *) tu cxTokens: (CXToken *) tokens count: (unsigned) count; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTokenSet.m: -------------------------------------------------------------------------------- 1 | #import "PLClangTokenSet.h" 2 | #import "PLClangTranslationUnit.h" 3 | #import "PLClangTranslationUnitPrivate.h" 4 | #import "PLAdditions.h" 5 | 6 | /** 7 | * @internal 8 | * Manages the lifetime of a set of CXTokens. 9 | * 10 | * A set of tokens returned by clang_tokenize() must be disposed at once 11 | * when the application is finished using all tokens in the set. This is 12 | * accomplished by having each PLClangToken retain an instance of this 13 | * object. 14 | */ 15 | @implementation PLClangTokenSet { 16 | /** 17 | * A reference to the owning translation unit, held so that the 18 | * CXTokens remain valid for the lifetime of the token set, and 19 | * because the translation unit is needed to dispose the tokens. 20 | */ 21 | PLClangTranslationUnit *_tu; 22 | 23 | /** The backing CXToken set. */ 24 | CXToken *_tokens; 25 | 26 | /** The number of tokens in the backing CXToken set. */ 27 | unsigned _count; 28 | } 29 | 30 | /** 31 | * Initialize a newly-created token set with the specified clang tokens. 32 | * 33 | * @param tu The translation unit in which the tokens reside. 34 | * @param tokens Pointer to the array of CXTokens this set should take ownership of. 35 | * @param count The number of CXTokens in the array. 36 | * @return An initialized token set. 37 | */ 38 | - (instancetype) initWithTranslationUnit: (PLClangTranslationUnit *) tu cxTokens: (CXToken *) tokens count: (unsigned) count { 39 | PLSuperInit(); 40 | 41 | _tu = tu; 42 | _tokens = tokens; 43 | _count = count; 44 | 45 | return self; 46 | } 47 | 48 | - (void) dealloc { 49 | if (_tokens) { 50 | clang_disposeTokens([_tu cxTranslationUnit], _tokens, _count); 51 | } 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTokenTests.m: -------------------------------------------------------------------------------- 1 | #import "PLClangTestCase.h" 2 | 3 | @interface PLClangTokenTests : PLClangTestCase 4 | @end 5 | 6 | @implementation PLClangTokenTests 7 | 8 | - (void) testTokenization { 9 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t = 1;"]; 10 | NSArray *tokens = [tu tokensForSourceRange: tu.cursor.extent]; 11 | XCTAssertNotNil(tokens, @"Failed to create tokens array"); 12 | XCTAssertEqual([tokens count], (NSUInteger)5, @"Source range should contain 5 tokens"); 13 | 14 | PLClangToken *token = tokens[0]; 15 | XCTAssertEqual(token.kind, PLClangTokenKindKeyword, @"Token should be the int keyword"); 16 | XCTAssertEqualObjects(token.spelling, @"int"); 17 | XCTAssertEqual(token.location.fileOffset, (off_t)0); 18 | XCTAssertEqual(token.extent.startLocation.fileOffset, (off_t)0); 19 | XCTAssertEqual(token.extent.endLocation.fileOffset, (off_t)3); 20 | XCTAssertEqual(token.cursor.kind, PLClangCursorKindVariableDeclaration, @"Token should be part of represent a variable definition"); 21 | 22 | token = tokens[1]; 23 | XCTAssertEqual(token.kind, PLClangTokenKindIdentifier, @"Token should be the t identifier"); 24 | XCTAssertEqualObjects(token.spelling, @"t"); 25 | XCTAssertEqual(token.location.fileOffset, (off_t)4); 26 | XCTAssertEqual(token.extent.startLocation.fileOffset, (off_t)4); 27 | XCTAssertEqual(token.extent.endLocation.fileOffset, (off_t)5); 28 | XCTAssertEqual(token.cursor.kind, PLClangCursorKindVariableDeclaration, @"Token should be part of represent a variable definition"); 29 | 30 | token = tokens[2]; 31 | XCTAssertEqual(token.kind, PLClangTokenKindPunctuation, @"Token should be the assignement operator"); 32 | XCTAssertEqualObjects(token.spelling, @"="); 33 | XCTAssertEqual(token.location.fileOffset, (off_t)6); 34 | XCTAssertEqual(token.extent.startLocation.fileOffset, (off_t)6); 35 | XCTAssertEqual(token.extent.endLocation.fileOffset, (off_t)7); 36 | XCTAssertEqual(token.cursor.kind, PLClangCursorKindVariableDeclaration, @"Token should be part of represent a variable definition"); 37 | 38 | token = tokens[3]; 39 | XCTAssertEqual(token.kind, PLClangTokenKindLiteral, @"Token should be the numeric literal"); 40 | XCTAssertEqualObjects(token.spelling, @"1"); 41 | XCTAssertEqual(token.location.fileOffset, (off_t)8); 42 | XCTAssertEqual(token.extent.startLocation.fileOffset, (off_t)8); 43 | XCTAssertEqual(token.extent.endLocation.fileOffset, (off_t)9); 44 | XCTAssertEqual(token.cursor.kind, PLClangCursorKindIntegerLiteral, @"Token should be the integer literal"); 45 | 46 | token = tokens[4]; 47 | XCTAssertEqual(token.kind, PLClangTokenKindPunctuation, @"Token should be the semicolon"); 48 | XCTAssertEqualObjects(token.spelling, @";"); 49 | XCTAssertEqual(token.location.fileOffset, (off_t)9); 50 | XCTAssertEqual(token.extent.startLocation.fileOffset, (off_t)9); 51 | XCTAssertEqual(token.extent.endLocation.fileOffset, (off_t)10); 52 | XCTAssertNil(token.cursor, @"Semicolon should not have a cursor"); 53 | } 54 | 55 | - (void) testComment { 56 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"/** A comment. */\n"]; 57 | NSArray *tokens = [tu tokensForSourceRange: tu.cursor.extent]; 58 | XCTAssertNotNil(tokens, @"Failed to create tokens array"); 59 | XCTAssertEqual([tokens count], (NSUInteger)1, @"Source range should contain 1 tokens"); 60 | 61 | PLClangToken *token = tokens[0]; 62 | XCTAssertEqual(token.kind, PLClangTokenKindComment, @"Token should be a comment"); 63 | XCTAssertEqualObjects(token.spelling, @"/** A comment. */"); 64 | XCTAssertEqual(token.location.fileOffset, (off_t)0); 65 | XCTAssertEqual(token.extent.startLocation.fileOffset, (off_t)0); 66 | XCTAssertEqual(token.extent.endLocation.fileOffset, (off_t)17); 67 | XCTAssertNil(token.cursor, @"Comment should not have a cursor"); 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTranslationUnit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | #import "PLClangCursor.h" 31 | #import "PLClangDiagnostic.h" 32 | #import "PLClangToken.h" 33 | 34 | @interface PLClangTranslationUnit : NSObject 35 | 36 | /** The original source file name of this translation unit. */ 37 | @property(nonatomic, readonly) NSString *spelling; 38 | 39 | /** An ordered array of PLClangDiagnostic instances generated by parsing this translation unit. */ 40 | @property(nonatomic, readonly) NSArray *diagnostics; 41 | 42 | /** If YES, the code could not be properly parsed and is ill-formed. Review the array of diagnostics for more details. */ 43 | @property(nonatomic, readonly) BOOL didFail; 44 | 45 | /** The cursor representing this translation unit. */ 46 | @property(nonatomic, readonly) PLClangCursor *cursor; 47 | 48 | - (PLClangCursor *) cursorForSourceLocation: (PLClangSourceLocation *) sourceLocation; 49 | - (NSArray *) tokensForSourceRange: (PLClangSourceRange *) range; 50 | - (BOOL) writeToFile: (NSString *) path error: (NSError **) error; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTranslationUnit.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | 31 | #import "PLAdditions.h" 32 | 33 | #import "PLClangTranslationUnit.h" 34 | #import "PLClangCursorPrivate.h" 35 | #import "PLClangDiagnostic.h" 36 | #import "PLClangDiagnosticPrivate.h" 37 | #import "PLClangSourceLocationPrivate.h" 38 | #import "PLClangSourceRangePrivate.h" 39 | #import "PLClangTokenPrivate.h" 40 | #import "PLClangTokenSet.h" 41 | #import "PLClangNSString.h" 42 | #import "PLClang.h" 43 | 44 | /** 45 | * A translation unit. 46 | */ 47 | @implementation PLClangTranslationUnit { 48 | @private 49 | /** 50 | * A reference to the owning object (the index), held so that the CXIndex 51 | * remains valid for the lifetime of the translation unit. 52 | */ 53 | id _owner; 54 | 55 | /** Backing clang translation unit. */ 56 | CXTranslationUnit _tu; 57 | } 58 | 59 | /** 60 | * @internal 61 | * Note that once a translation unit has been disposed all clang objects derived from it become 62 | * invalid. This includes comments, cursors, locations, and tokens. 63 | */ 64 | - (void) dealloc { 65 | if (_tu != NULL) 66 | clang_disposeTranslationUnit(_tu); 67 | } 68 | 69 | // property getter 70 | - (BOOL) didFail { 71 | for (PLClangDiagnostic *d in _diagnostics) { 72 | if (d.severity == PLClangDiagnosticSeverityError || d.severity == PLClangDiagnosticSeverityFatal) 73 | return YES; 74 | } 75 | 76 | return NO; 77 | } 78 | 79 | /* 80 | * The cursor holds a strong reference to the translation unit so that the backing CXTranslationUnit 81 | * remains valid for the lifetime of the cursor. To avoid a retain cycle the translation unit does 82 | * not retain its cursor. 83 | */ 84 | - (PLClangCursor *) cursor { 85 | return [[PLClangCursor alloc] initWithOwner: self cxCursor: clang_getTranslationUnitCursor(_tu)]; 86 | } 87 | 88 | /** 89 | * Maps a source location within the translation unit to to the most specific 90 | * cursor that describes the entity at that location. 91 | * 92 | * For example, given an expression "x + y", invoking this method 93 | * with a source location pointing to "x" will return the cursor for "x". 94 | * If the cursor points anywhere between "x" or "y" (e.g., on the + or the whitespace 95 | * around it), this method will return a cursor referring to the "+" expression. 96 | * 97 | * @return A cursor representing the entity at the given source location, or 98 | * nil if no such entity can be mapped. 99 | */ 100 | - (PLClangCursor *) cursorForSourceLocation: (PLClangSourceLocation *) sourceLocation { 101 | return [[PLClangCursor alloc] initWithOwner: self cxCursor: clang_getCursor(_tu, [sourceLocation cxSourceLocation])]; 102 | } 103 | 104 | /** 105 | * Tokenize the source code described by the given range into raw lexical tokens. 106 | * 107 | * @param range The source range in which text should be tokenized. 108 | * 109 | * @return An array of PLClangToken objects that occur within the given source range. 110 | */ 111 | - (NSArray *) tokensForSourceRange: (PLClangSourceRange *) range { 112 | CXToken *cxTokens = NULL; 113 | unsigned int tokenCount = 0; 114 | clang_tokenize(_tu, [range cxSourceRange], &cxTokens, &tokenCount); 115 | 116 | NSMutableArray *tokens = [NSMutableArray arrayWithCapacity: tokenCount]; 117 | if (tokenCount < 1) 118 | return tokens; 119 | 120 | CXCursor* cxCursors = (CXCursor *)calloc(tokenCount, sizeof(CXCursor)); 121 | clang_annotateTokens(_tu, cxTokens, tokenCount, cxCursors); 122 | 123 | // The token set is retained by each token so that clang_disposeTokens() is only called 124 | // when the last PLClangToken is deallocated. 125 | PLClangTokenSet *tokenSet = [[PLClangTokenSet alloc] initWithTranslationUnit: self cxTokens: cxTokens count: tokenCount]; 126 | 127 | for (unsigned int i = 0; i < tokenCount; i++) { 128 | PLClangCursor *cursor = [[PLClangCursor alloc] initWithOwner: self cxCursor: cxCursors[i]]; 129 | [tokens addObject: [[PLClangToken alloc] initWithOwner: tokenSet 130 | translationUnit: self 131 | cursor: cursor 132 | cxToken: cxTokens[i]]]; 133 | } 134 | 135 | free(cxCursors); 136 | return tokens; 137 | } 138 | 139 | /** 140 | * Writes the translation unit to the specified location as an AST file. 141 | * 142 | * Typically this is used to create a precompiled header. The translation unit should be created with 143 | * the PLClangTranslationUnitCreationForSerialization option. 144 | * 145 | * @param path The path where the translation unit should be written. 146 | * @param error If an error occurs, upon return contains an NSError object that describes the problem. 147 | * If you are not interested in possible errors, pass in nil. 148 | * @return YES if the translation unit was successfully saved, or NO if an error occurred. 149 | */ 150 | - (BOOL) writeToFile: (NSString *) path error: (NSError **) error { 151 | if (error) 152 | *error = nil; 153 | 154 | enum CXSaveError result = (enum CXSaveError)clang_saveTranslationUnit(_tu, [path fileSystemRepresentation], clang_defaultSaveOptions(_tu)); 155 | 156 | PLClangErrorCode errorCode = PLClangErrorUnknown; 157 | NSString *description = NSLocalizedString(@"An unknown error occurred while saving the translation unit.", nil); 158 | 159 | switch (result) { 160 | case CXSaveError_None: 161 | return YES; 162 | case CXSaveError_Unknown: 163 | errorCode = PLClangErrorSaveFailed; 164 | description = NSLocalizedString(@"The translation unit could not be written to disk.", nil); 165 | break; 166 | case CXSaveError_TranslationErrors: 167 | // As of libclang 0.20 it defines but does not actually use this error condition 168 | errorCode = PLClangErrorCompiler; 169 | description = NSLocalizedString(@"Translation errors prevented the operation from completing.", nil); 170 | break; 171 | case CXSaveError_InvalidTU: 172 | errorCode = PLClangErrorInvalidTranslationUnit; 173 | description = NSLocalizedString(@"The translation unit is invalid.", nil); 174 | break; 175 | } 176 | 177 | if (error) { 178 | *error = [NSError errorWithDomain: PLClangErrorDomain code: errorCode userInfo: @{ 179 | NSLocalizedDescriptionKey: description 180 | }]; 181 | } 182 | 183 | return NO; 184 | } 185 | 186 | - (NSString *) description { 187 | return self.spelling; 188 | } 189 | 190 | - (NSString *) debugDescription { 191 | return [NSString stringWithFormat: @"<%@: %p> %@", [self class], self, [self description]]; 192 | } 193 | 194 | @end 195 | 196 | /** 197 | * @internal 198 | * Package-private methods. 199 | */ 200 | @implementation PLClangTranslationUnit (PackagePrivate) 201 | 202 | /** 203 | * Initialize with the given translation unit. 204 | * 205 | * @param owner A reference to the owner of the clang translation unit. This reference will be 206 | * retained to ensure that the clang translation unit survives for the lifetime of this instance. 207 | * @param tu Backing clang translation unit. The receiver will assume ownership over the value. 208 | */ 209 | - (instancetype) initWithOwner: (id) owner cxTranslationUnit: (CXTranslationUnit) tu { 210 | PLSuperInit(); 211 | 212 | _owner = owner; 213 | _tu = tu; 214 | _spelling = plclang_convert_and_dispose_cxstring(clang_getTranslationUnitSpelling(_tu)); 215 | 216 | /* Extract all diagnostics */ 217 | CXDiagnosticSet diagnosticSet = clang_getDiagnosticSetFromTU(tu); 218 | unsigned int count = clang_getNumDiagnosticsInSet(diagnosticSet); 219 | NSMutableArray *diagnostics = [NSMutableArray arrayWithCapacity: count]; 220 | for (unsigned int i = 0; i < count; i++) { 221 | CXDiagnostic diagnostic = clang_getDiagnosticInSet(diagnosticSet, i); 222 | if (clang_getDiagnosticSeverity(diagnostic) == CXDiagnostic_Note) { 223 | // TODO: Handle note diagnostics. 224 | continue; 225 | } 226 | 227 | [diagnostics addObject: [[PLClangDiagnostic alloc] initWithCXDiagnostic: diagnostic]]; 228 | } 229 | _diagnostics = diagnostics; 230 | 231 | // TODO: Verify that clang does not dispose backing storage required by the CXDiagnostic instances. 232 | clang_disposeDiagnosticSet(diagnosticSet); 233 | 234 | return self; 235 | } 236 | 237 | - (CXTranslationUnit) cxTranslationUnit { 238 | return _tu; 239 | } 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTranslationUnitPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | #import "PLClangTranslationUnit.h" 31 | 32 | #import 33 | 34 | @interface PLClangTranslationUnit (PackagePrivate) 35 | 36 | - (instancetype) initWithOwner: (id) owner cxTranslationUnit: (CXTranslationUnit) tu; 37 | - (CXTranslationUnit) cxTranslationUnit; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTranslationUnitTests.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangTestCase.h" 8 | 9 | @interface PLClangTranslationUnitTests : PLClangTestCase @end 10 | 11 | @implementation PLClangTranslationUnitTests { 12 | NSString *_tempDirectory; 13 | } 14 | 15 | - (void) setUp { 16 | [super setUp]; 17 | NSString *bundleId = [[NSBundle bundleForClass: [self class]] bundleIdentifier]; 18 | _tempDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent: bundleId]; 19 | [[NSFileManager defaultManager] removeItemAtPath: _tempDirectory error: nil]; 20 | BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath: _tempDirectory withIntermediateDirectories: YES attributes: nil error: nil]; 21 | XCTAssertTrue(result, @"Failed to create temporary directory"); 22 | } 23 | 24 | - (void) tearDown { 25 | BOOL result = [[NSFileManager defaultManager] removeItemAtPath: _tempDirectory error: nil]; 26 | XCTAssertTrue(result, @"Failed to remove temporary directory"); 27 | [super tearDown]; 28 | } 29 | 30 | /** 31 | * Test basic parsing 32 | */ 33 | - (void) testParsing { 34 | NSError *error = nil; 35 | NSData *test = [@"int main (int argc, char *argv[]) { return 0; }" dataUsingEncoding: NSUTF8StringEncoding]; 36 | PLClangTranslationUnit *tu = [_index addTranslationUnitWithSourcePath: @"test.c" fileData: test compilerArguments: @[] options: 0 error: &error]; 37 | XCTAssertNotNil(tu, @"Failed to parse", nil); 38 | XCTAssertNil(error, @"Received error for successful parse"); 39 | XCTAssertEqualObjects(tu.spelling, @"test.c"); 40 | XCTAssertNotNil(tu.cursor, @"Translation unit should have a cursor"); 41 | XCTAssertEqual(tu.cursor.kind, PLClangCursorKindTranslationUnit, @"Cursor should be a translation unit cursor"); 42 | 43 | XCTAssertFalse(tu.didFail, @"Should be marked as non-failed: %@", tu.diagnostics); 44 | XCTAssertTrue([tu.diagnostics count] == 0, @"No diagnostics should be returned"); 45 | } 46 | 47 | /** 48 | * Test extraction of compiler diagnostics. 49 | */ 50 | - (void) testExtractDiagnostics { 51 | NSError *error = nil; 52 | NSData *test = [@"PARSE ERROR int main (int argc, char *argv[]) { return 0; }" dataUsingEncoding: NSUTF8StringEncoding]; 53 | PLClangTranslationUnit *tu = [_index addTranslationUnitWithSourcePath: @"test.c" fileData: test compilerArguments: @[] options: 0 error: &error]; 54 | XCTAssertNotNil(tu, @"Failed to parse", nil); 55 | XCTAssertNil(error, @"Received error for successful parse"); 56 | XCTAssertEqualObjects(tu.spelling, @"test.c"); 57 | XCTAssertNotNil(tu.cursor, @"Translation unit should have a cursor"); 58 | XCTAssertEqual(tu.cursor.kind, PLClangCursorKindTranslationUnit, @"Cursor should be a translation unit cursor"); 59 | 60 | XCTAssertTrue(tu.didFail, @"Should be marked as failed"); 61 | XCTAssertTrue([tu.diagnostics count] > 0, @"No diagnostics returned"); 62 | for (PLClangDiagnostic *diag in tu.diagnostics) { 63 | XCTAssertNotNil(diag.formattedErrorMessage, @"No error message returned"); 64 | } 65 | } 66 | 67 | /** 68 | * Test that macro definitions are included when the detailed preprocessing record is enabled. 69 | */ 70 | - (void) testDetailedPreprocessing { 71 | NSError *error = nil; 72 | NSData *test = [@"#define MACRO 1" dataUsingEncoding: NSUTF8StringEncoding]; 73 | PLClangTranslationUnit *tu = [_index addTranslationUnitWithSourcePath: @"test.c" fileData: test compilerArguments: @[] options: 0 error: &error]; 74 | XCTAssertNotNil(tu, @"Failed to parse", nil); 75 | XCTAssertNil(error, @"Received error for successful parse"); 76 | XCTAssertEqualObjects(tu.spelling, @"test.c"); 77 | XCTAssertNotNil(tu.cursor, @"Translation unit should have a cursor"); 78 | XCTAssertEqual(tu.cursor.kind, PLClangCursorKindTranslationUnit, @"Cursor should be a translation unit cursor"); 79 | XCTAssertNil([tu cursorWithSpelling: @"MACRO"], @"Should not have found macro definition without detailed preprocessing record"); 80 | 81 | tu = [_index addTranslationUnitWithSourcePath: @"test.c" fileData: test compilerArguments: @[] options: PLClangTranslationUnitCreationDetailedPreprocessingRecord error: &error]; 82 | XCTAssertNotNil(tu, @"Failed to parse", nil); 83 | XCTAssertNil(error, @"Received error for successful parse"); 84 | XCTAssertEqualObjects(tu.spelling, @"test.c"); 85 | XCTAssertNotNil(tu.cursor, @"Translation unit should have a cursor"); 86 | XCTAssertEqual(tu.cursor.kind, PLClangCursorKindTranslationUnit, @"Cursor should be a translation unit cursor"); 87 | XCTAssertNotNil([tu cursorWithSpelling: @"MACRO"], @"Should have found macro definition with detailed preprocessing record"); 88 | } 89 | 90 | /** 91 | * Test that a cursor can be obtained from a source location. 92 | */ 93 | - (void) testCursorForLocation { 94 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t;" path: @"test.c"]; 95 | PLClangSourceLocation *location = [[PLClangSourceLocation alloc] initWithTranslationUnit: tu 96 | file: @"test.c" 97 | offset: 4]; 98 | XCTAssertNotNil(location, @"Could not create source location"); 99 | PLClangCursor *cursor = [tu cursorForSourceLocation: location]; 100 | XCTAssertNotNil(cursor, @"Could not map cursor"); 101 | XCTAssertEqual(cursor.kind, PLClangCursorKindVariableDeclaration, @"Cursor should be a variable declaration"); 102 | } 103 | 104 | /** 105 | * Tests that a translation unit can be saved to an AST file and a new translation unit created from it. 106 | */ 107 | - (void) testASTFileSaveAndLoad { 108 | NSError *error = nil; 109 | NSString *path = [_tempDirectory stringByAppendingPathComponent: @"test.pch"]; 110 | 111 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f();" 112 | path: @"test.h" 113 | options: PLClangTranslationUnitCreationIncomplete | 114 | PLClangTranslationUnitCreationForSerialization]; 115 | BOOL result = [tu writeToFile: path error: &error]; 116 | XCTAssertTrue(result, @"Failed to save translation unit"); 117 | XCTAssertNil(error, @"Received error for translation unit save"); 118 | 119 | PLClangSourceIndex *index = [PLClangSourceIndex new]; 120 | tu = [index addTranslationUnitWithASTPath: path error: &error]; 121 | XCTAssertNotNil(tu, @"Failed to parse", nil); 122 | XCTAssertNil(error, @"Received error for successful parse"); 123 | XCTAssertFalse(tu.didFail, @"Should be marked as non-failed: %@", tu.diagnostics); 124 | PLClangCursor *cursor = [tu cursorWithSpelling: @"f"]; 125 | XCTAssertNotNil(cursor, @"Failed to locate cursor in translation unit loaded from AST file"); 126 | } 127 | 128 | - (void) testASTFileWriteToInvalidPath { 129 | NSError *error = nil; 130 | NSString *path = [_tempDirectory stringByAppendingPathComponent: @"notfound/test.pch"]; 131 | 132 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f();" 133 | path: @"test.h" 134 | options: PLClangTranslationUnitCreationIncomplete | 135 | PLClangTranslationUnitCreationForSerialization]; 136 | BOOL result = [tu writeToFile: path error: &error]; 137 | XCTAssertFalse(result, @"Translation unit save should have failed"); 138 | XCTAssertNotNil(error, @"Should have received error for translation unit save"); 139 | XCTAssertEqualObjects(error.domain, PLClangErrorDomain); 140 | XCTAssertEqual(error.code, PLClangErrorSaveFailed); 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangType.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | @class PLClangCursor; 8 | @class PLClangType; 9 | 10 | /** 11 | * The kind of a PLClangType. 12 | */ 13 | typedef NS_ENUM(NSUInteger, PLClangTypeKind) { 14 | /** A type whose specific kind is not exposed via this interface. */ 15 | PLClangTypeKindUnexposed = 1, 16 | 17 | /** void */ 18 | PLClangTypeKindVoid = 2, 19 | 20 | /** bool in C++ or _Bool in C99 */ 21 | PLClangTypeKindBool = 3, 22 | 23 | /** char for targets where it's unsigned */ 24 | PLClangTypeKindCharUnsignedTarget = 4, 25 | 26 | /** unsigned char, explicitly qualified */ 27 | PLClangTypeKindUnsignedChar = 5, 28 | 29 | /** char16_t in C++ */ 30 | PLClangTypeKindChar16 = 6, 31 | 32 | /** char32_t in C++ */ 33 | PLClangTypeKindChar32 = 7, 34 | 35 | /** unsigned short */ 36 | PLClangTypeKindUnsignedShort = 8, 37 | 38 | /** unsigned int */ 39 | PLClangTypeKindUnsignedInt = 9, 40 | 41 | /** unsigned long */ 42 | PLClangTypeKindUnsignedLong = 10, 43 | 44 | /** unsigned long long */ 45 | PLClangTypeKindUnsignedLongLong = 11, 46 | 47 | /** __uint128_t */ 48 | PLClangTypeKindUInt128 = 12, 49 | 50 | /** char for targets where it's signed */ 51 | PLClangTypeKindCharSignedTarget = 13, 52 | 53 | /** signed char, explicitly qualified */ 54 | PLClangTypeKindSignedChar = 14, 55 | 56 | /** wchar_t */ 57 | PLClangTypeKindWChar = 15, 58 | 59 | /** short or signed short */ 60 | PLClangTypeKindShort = 16, 61 | 62 | /** int or signed int */ 63 | PLClangTypeKindInt = 17, 64 | 65 | /** long or signed long */ 66 | PLClangTypeKindLong = 18, 67 | 68 | /** long long or signed long long */ 69 | PLClangTypeKindLongLong = 19, 70 | 71 | /** __int128_t */ 72 | PLClangTypeKindInt128 = 20, 73 | 74 | /** float */ 75 | PLClangTypeKindFloat = 21, 76 | 77 | /** double */ 78 | PLClangTypeKindDouble = 22, 79 | 80 | /** long double */ 81 | PLClangTypeKindLongDouble = 23, 82 | 83 | /** nullptr */ 84 | PLClangTypeKindNullPtr = 24, 85 | 86 | /** A type of an unresolved overload set. */ 87 | PLClangTypeKindOverload = 25, 88 | 89 | /** 90 | * A type of an expression whose type is unknown, such as "T::foo". 91 | * 92 | * It is permitted for this to appear in situations where the structure of the type 93 | * is theoretically deducible. 94 | */ 95 | PLClangTypeKindDependent = 26, 96 | 97 | /** id in Objective-C */ 98 | PLClangTypeKindObjCId = 27, 99 | 100 | /** Class in Objective-C */ 101 | PLClangTypeKindObjCClass = 28, 102 | 103 | /** SEL in Objective-C */ 104 | PLClangTypeKindObjCSel = 29, 105 | 106 | /** __float128 */ 107 | PLClangTypeKindFloat128 = 30, 108 | 109 | /** A complex type. */ 110 | PLClangTypeKindComplex = 100, 111 | 112 | /** A pointer. */ 113 | PLClangTypeKindPointer = 101, 114 | 115 | /** A pointer to a block. */ 116 | PLClangTypeKindBlockPointer = 102, 117 | 118 | /** An lvalue reference. */ 119 | PLClangTypeKindLValueReference = 103, 120 | 121 | /** An rvalue reference. */ 122 | PLClangTypeKindRValueReference = 104, 123 | 124 | /** A record. */ 125 | PLClangTypeKindRecord = 105, 126 | 127 | /** An enum. */ 128 | PLClangTypeKindEnum = 106, 129 | 130 | /** A typedef. */ 131 | PLClangTypeKindTypedef = 107, 132 | 133 | /** An Objective-C interface. */ 134 | PLClangTypeKindObjCInterface = 108, 135 | 136 | /** A pointer to an Objective-C object. */ 137 | PLClangTypeKindObjCObjectPointer = 109, 138 | 139 | /** A function that has no argument information, such as "int foo()". */ 140 | PLClangTypeKindFunctionNoPrototype = 110, 141 | 142 | /** A function prototype that has argument information, such as "int foo(int) or "int foo(void)". */ 143 | PLClangTypeKindFunctionPrototype = 111, 144 | 145 | /** A C array with a specified constant size. */ 146 | PLClangTypeKindConstantArray = 112, 147 | 148 | /** A generic vector. */ 149 | PLClangTypeKindVector = 113, 150 | 151 | /** A C array with an unspecified size, such as "int a[]". */ 152 | PLClangTypeKindIncompleteArray = 114, 153 | 154 | /** A C array with a non-constant size, such as "int a[x+foo()]". */ 155 | PLClangTypeKindVariableArray = 115, 156 | 157 | /** 158 | * A C++ array type whose size is a value-dependent expression. 159 | * 160 | * For example: 161 | * 162 | * @code 163 | * template 164 | * class array { 165 | * T data[Size]; 166 | * } 167 | * @endcode 168 | */ 169 | PLClangTypeKindDependentSizedArray = 116, 170 | 171 | /** A C++ member pointer. */ 172 | PLClangTypeKindMemberPointer = 117, 173 | 174 | /** A C++11 auto or C++14 decltype(auto) type. */ 175 | PLClangTypeKindAuto = 118, 176 | 177 | /** 178 | * A type that was referred to using an elaborated type keyword. 179 | * 180 | * E.g., struct S, or via a qualified name, e.g., N::M::type, or both. 181 | */ 182 | PLClangTypeKindElaborated = 119 183 | }; 184 | 185 | @interface PLClangType : NSObject 186 | 187 | @property(nonatomic, readonly) PLClangTypeKind kind; 188 | 189 | /** 190 | * A string representation of the type. 191 | */ 192 | @property(nonatomic, readonly) NSString *spelling; 193 | @property(nonatomic, readonly) PLClangCursor *declaration; 194 | 195 | @property(nonatomic, readonly) BOOL isConstQualified; 196 | @property(nonatomic, readonly) BOOL isRestrictQualified; 197 | @property(nonatomic, readonly) BOOL isVolatileQualified; 198 | @property(nonatomic, readonly) BOOL isPOD; 199 | @property(nonatomic, readonly) BOOL isVariadic; 200 | 201 | @property(nonatomic, readonly) PLClangType *canonicalType; 202 | @property(nonatomic, readonly) PLClangType *resultType; 203 | @property(nonatomic, readonly) PLClangType *pointeeType; 204 | @property(nonatomic, readonly) PLClangType *elementType; 205 | @property(nonatomic, readonly) long long numberOfElements; 206 | @property(nonatomic, readonly) NSArray *argumentTypes; 207 | 208 | @end 209 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTypePrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangType.h" 8 | 9 | #import 10 | 11 | @interface PLClangType (PackagePrivate) 12 | 13 | - (instancetype) initWithOwner: (id) owner cxType: (CXType) type; 14 | - (CXType) cxType; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangTypeTests.m: -------------------------------------------------------------------------------- 1 | #import "PLClangTestCase.h" 2 | 3 | @interface PLClangTypeTests : PLClangTestCase 4 | @end 5 | 6 | @implementation PLClangTypeTests 7 | 8 | - (void) testInt { 9 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t;"]; 10 | PLClangType *type = [[tu cursorWithSpelling: @"t"] type]; 11 | XCTAssertNotNil(type); 12 | XCTAssertEqual(type.kind, PLClangTypeKindInt); 13 | XCTAssertEqualObjects(type.spelling, @"int"); 14 | XCTAssertNil(type.declaration); 15 | XCTAssertNil(type.resultType); 16 | XCTAssertNil(type.pointeeType); 17 | XCTAssertNil(type.elementType); 18 | XCTAssertNil(type.argumentTypes); 19 | XCTAssertTrue(type.numberOfElements == -1, @"Should not have had an element count, not a constant array type"); 20 | 21 | XCTAssertEqualObjects(type.canonicalType, type, @"Type should have been its canonical type"); 22 | } 23 | 24 | - (void) testConstantArray { 25 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t[2];"]; 26 | PLClangType *type = [[tu cursorWithSpelling: @"t"] type]; 27 | XCTAssertNotNil(type); 28 | XCTAssertEqual(type.kind, PLClangTypeKindConstantArray); 29 | XCTAssertEqualObjects(type.spelling, @"int [2]"); 30 | XCTAssertNil(type.declaration); 31 | XCTAssertNil(type.resultType); 32 | XCTAssertNil(type.pointeeType); 33 | XCTAssertNotNil(type.elementType); 34 | XCTAssertNil(type.argumentTypes); 35 | XCTAssertTrue(type.numberOfElements == 2, @"Constant array should have had 2 elements"); 36 | 37 | XCTAssertEqualObjects(type.canonicalType, type, @"Type should have been its canonical type"); 38 | XCTAssertEqual(type.elementType.kind, PLClangTypeKindInt); 39 | } 40 | 41 | - (void) testPointer { 42 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int *t;"]; 43 | PLClangType *type = [[tu cursorWithSpelling: @"t"] type]; 44 | XCTAssertNotNil(type); 45 | XCTAssertEqual(type.kind, PLClangTypeKindPointer); 46 | XCTAssertEqualObjects(type.spelling, @"int *"); 47 | XCTAssertNil(type.declaration); 48 | XCTAssertNil(type.resultType); 49 | XCTAssertNotNil(type.pointeeType); 50 | XCTAssertNil(type.elementType); 51 | XCTAssertNil(type.argumentTypes); 52 | XCTAssertTrue(type.numberOfElements == -1, @"Should not have had an element count, not a constant array type"); 53 | 54 | XCTAssertEqualObjects(type.canonicalType, type, @"Type should have been its canonical type"); 55 | XCTAssertEqual(type.pointeeType.kind, PLClangTypeKindInt); 56 | } 57 | 58 | - (void) testTypedef { 59 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"typedef int type; type t; int o;"]; 60 | PLClangType *type = [[tu cursorWithSpelling: @"t"] type]; 61 | XCTAssertEqual(type.kind, PLClangTypeKindTypedef); 62 | XCTAssertEqualObjects(type.spelling, @"type"); 63 | XCTAssertNotNil(type.declaration); 64 | XCTAssertNil(type.resultType); 65 | XCTAssertNil(type.pointeeType); 66 | XCTAssertNil(type.elementType); 67 | XCTAssertNil(type.argumentTypes); 68 | XCTAssertTrue(type.numberOfElements == -1, @"Should not have had an element count, not a constant array type"); 69 | XCTAssertFalse([type.canonicalType isEqual: type], @"Typedef should not have been its canonical type"); 70 | 71 | XCTAssertEqual(type.canonicalType.kind, PLClangTypeKindInt, @"Typedef's canonical type should have been int"); 72 | 73 | PLClangType *intType = [[tu cursorWithSpelling: @"o"] type]; 74 | XCTAssertNotNil(type); 75 | XCTAssertEqualObjects(type.canonicalType, intType, @"Canonical type should have been equal to non-typedefed int type"); 76 | } 77 | 78 | - (void) testMultiLevelTypedef { 79 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"typedef int base; typedef base type; type t;"]; 80 | PLClangType *type = [[tu cursorWithSpelling: @"t"] type]; 81 | XCTAssertEqual(type.kind, PLClangTypeKindTypedef); 82 | XCTAssertEqualObjects(type.spelling, @"type"); 83 | XCTAssertEqual(type.canonicalType.kind, PLClangTypeKindInt, @"Multi-level typedef's canonical type should have been int"); 84 | } 85 | 86 | - (void) testFunction { 87 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f(int p);"]; 88 | PLClangType *type = [[tu cursorWithSpelling: @"f"] type]; 89 | XCTAssertEqual(type.kind, PLClangTypeKindFunctionPrototype); 90 | XCTAssertEqualObjects(type.spelling, @"void (int)"); 91 | XCTAssertNil(type.declaration); 92 | XCTAssertNotNil(type.resultType); 93 | XCTAssertNil(type.pointeeType); 94 | XCTAssertNil(type.elementType); 95 | XCTAssertNotNil(type.argumentTypes); 96 | XCTAssertTrue(type.numberOfElements == -1, @"Should not have had an element count, not a constant array type"); 97 | 98 | XCTAssertEqualObjects(type.canonicalType, type, @"Type should have been its canonical type"); 99 | XCTAssertEqual(type.resultType.kind, PLClangTypeKindVoid); 100 | 101 | XCTAssertTrue([type.argumentTypes count] == 1, @"Function type should have had an argument type"); 102 | 103 | PLClangType *argType = type.argumentTypes[0]; 104 | XCTAssertEqual(argType.kind, PLClangTypeKindInt); 105 | } 106 | 107 | - (void) testQualifiers { 108 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"int t;"]; 109 | PLClangType *type = [[tu cursorWithSpelling: @"t"] type]; 110 | XCTAssertNotNil(type); 111 | XCTAssertFalse(type.isConstQualified); 112 | XCTAssertFalse(type.isRestrictQualified); 113 | XCTAssertFalse(type.isVolatileQualified); 114 | 115 | tu = [self translationUnitWithSource: @"const int t = 1;"]; 116 | type = [[tu cursorWithSpelling: @"t"] type]; 117 | XCTAssertNotNil(type); 118 | XCTAssertTrue(type.isConstQualified); 119 | XCTAssertFalse(type.isRestrictQualified); 120 | XCTAssertFalse(type.isVolatileQualified); 121 | 122 | tu = [self translationUnitWithSource: @"int * restrict t;"]; 123 | type = [[tu cursorWithSpelling: @"t"] type]; 124 | XCTAssertNotNil(type); 125 | XCTAssertFalse(type.isConstQualified); 126 | XCTAssertTrue(type.isRestrictQualified); 127 | XCTAssertFalse(type.isVolatileQualified); 128 | 129 | tu = [self translationUnitWithSource: @"volatile int t;"]; 130 | type = [[tu cursorWithSpelling: @"t"] type]; 131 | XCTAssertNotNil(type); 132 | XCTAssertFalse(type.isConstQualified); 133 | XCTAssertFalse(type.isRestrictQualified); 134 | XCTAssertTrue(type.isVolatileQualified); 135 | } 136 | 137 | - (void) testPOD { 138 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"class T {};" path: @"test.cpp"]; 139 | PLClangCursor *cursor = [tu cursorWithSpelling: @"T"]; 140 | XCTAssertNotNil(cursor); 141 | XCTAssertTrue(cursor.type.isPOD, @"Class should have been a POD type"); 142 | 143 | tu = [self translationUnitWithSource: @"class T { ~T() {} };" path: @"test.cpp"]; 144 | cursor = [tu cursorWithSpelling: @"T"]; 145 | XCTAssertNotNil(cursor); 146 | XCTAssertFalse(cursor.type.isPOD, @"Class should not have been a POD type"); 147 | } 148 | 149 | - (void) testVariadic { 150 | PLClangTranslationUnit *tu = [self translationUnitWithSource: @"void f(int p, ...);"]; 151 | PLClangCursor *cursor = [tu cursorWithSpelling: @"f"]; 152 | XCTAssertNotNil(cursor); 153 | XCTAssertTrue(cursor.type.isVariadic, @"Function should have been variadic"); 154 | 155 | tu = [self translationUnitWithSource: @"void f(int p);"]; 156 | cursor = [tu cursorWithSpelling: @"f"]; 157 | XCTAssertNotNil(cursor); 158 | XCTAssertFalse(cursor.type.isVariadic, @"Function should not have been variadic"); 159 | } 160 | 161 | @end 162 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangUnsavedFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | @interface PLClangUnsavedFile : NSObject 9 | 10 | + (instancetype) unsavedFileWithPath: (NSString *) path data: (NSData *) data; 11 | 12 | /** 13 | * The path where the file is expected to be stored on disk. 14 | */ 15 | @property(nonatomic, readonly) NSString *path; 16 | 17 | /** 18 | * The file's data. 19 | */ 20 | @property(nonatomic, readonly) NSData *data; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangUnsavedFile.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangUnsavedFile.h" 7 | #import "PLAdditions.h" 8 | 9 | /** 10 | * The contents of a file within a translation unit that has not yet been saved to disk. 11 | */ 12 | @implementation PLClangUnsavedFile 13 | 14 | /** 15 | * Initializes an unsaved file with the specified expected path and data. 16 | * 17 | * @param path The path where the file is expected to be saved. This is used when 18 | * evaluating inclusion directives within the translation unit. 19 | * @param data The unsaved data for this file. 20 | */ 21 | - (instancetype) initWithPath: (NSString *) path data: (NSData *) data { 22 | PLSuperInit(); 23 | 24 | _path = path; 25 | _data = data; 26 | 27 | return self; 28 | } 29 | 30 | /** 31 | * Creates and returns an unsaved file with the specified expected path and data. 32 | * 33 | * @param path The path where the file is expected to be saved. This is used when 34 | * evaluating inclusion directives within the translation unit. 35 | * @param data The unsaved data for this file. 36 | */ 37 | + (instancetype) unsavedFileWithPath: (NSString *) path data: (NSData *) data { 38 | return [[self alloc] initWithPath: path data: data]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangVersion.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | @interface PLClangVersion : NSObject 9 | 10 | /** 11 | * The major version number, for example the 10 in 10.7.3. 12 | */ 13 | @property(nonatomic, readonly) int major; 14 | 15 | /** 16 | * The minor version number, for example the 7 in 10.7.3. 17 | * 18 | * The value of this property will be -1 if no minor version number was provided. 19 | */ 20 | @property(nonatomic, readonly) int minor; 21 | 22 | /** 23 | * The patch version number, for example the 3 in 10.7.3. 24 | * 25 | * The value of this property will be -1 if no patch version number was provided. 26 | */ 27 | @property(nonatomic, readonly) int patch; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangVersion.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLClangVersion.h" 7 | #import "PLClangVersionPrivate.h" 8 | #import "PLAdditions.h" 9 | 10 | /** 11 | * A version number. 12 | */ 13 | @implementation PLClangVersion 14 | 15 | - (NSString *) description { 16 | NSMutableString *string = [NSMutableString stringWithFormat: @"%d", self.major]; 17 | 18 | if (self.minor >= 0) { 19 | [string appendFormat: @".%d", self.minor]; 20 | } 21 | 22 | if (self.patch >= 0) { 23 | [string appendFormat: @".%d", self.patch]; 24 | } 25 | 26 | return string; 27 | } 28 | 29 | @end 30 | 31 | /** 32 | * @internal 33 | * Package-private methods. 34 | */ 35 | @implementation PLClangVersion (PackagePrivate) 36 | 37 | /** 38 | * Initialize a newly-created version with the specified clang version. 39 | * 40 | * @param version The clang version that will provide version information. 41 | * @return An initialized version. 42 | */ 43 | - (instancetype) initWithCXVersion: (CXVersion) version { 44 | PLSuperInit(); 45 | 46 | // A negative major version indicates that no version information was provided 47 | if (version.Major < 0) 48 | return nil; 49 | 50 | _major = version.Major; 51 | _minor = version.Minor; 52 | _patch = version.Subminor; 53 | 54 | return self; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /ObjectDoc/PLClangVersionPrivate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangVersion.h" 8 | 9 | #import 10 | 11 | @interface PLClangVersion (PackagePrivate) 12 | 13 | - (instancetype) initWithCXVersion: (CXVersion) version; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ObjectDoc/PLSourceLocation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | @interface PLSourceLocation : NSObject 9 | 10 | - (instancetype) initWithFilePath: (NSString *) filePath 11 | fileOffset: (off_t) fileOffset 12 | lineNumber: (NSUInteger) lineNumber 13 | columnNumber: (NSUInteger) columnNumber; 14 | 15 | /** 16 | * The file's reported path. This is simply the path as provided to the compiler, and may 17 | * be relative to an arbitrary build root. 18 | */ 19 | @property(nonatomic, readonly) NSString *filePath; 20 | 21 | /** 22 | * The byte offset into the source file. 23 | */ 24 | @property(nonatomic, readonly) off_t fileOffset; 25 | 26 | /** 27 | * The line position (0-indexed). 28 | */ 29 | @property(nonatomic, readonly) NSUInteger lineNumber; 30 | 31 | /** 32 | * The column position (0-indexed). 33 | */ 34 | @property(nonatomic, readonly) NSUInteger columnNumber; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ObjectDoc/PLSourceLocation.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "PLSourceLocation.h" 7 | #import "PLAdditions.h" 8 | 9 | /** 10 | * PLSourceLocation represents a specific source location based on file name, 11 | * line number, and column number. 12 | */ 13 | @implementation PLSourceLocation { 14 | @private 15 | } 16 | 17 | /** 18 | * Initialize a new source location instance. 19 | * 20 | * @param filePath The file's reported path. This is simply the path as provided to the compiler, and may 21 | * be relative to an arbitrary build root. 22 | * @param fileOffset Byte offset to the file position. 23 | * @param lineNumber The line position (0-indexed). 24 | * @param columnNumber The column position (0-indexed). 25 | */ 26 | - (instancetype) initWithFilePath: (NSString *) filePath fileOffset: (off_t) fileOffset lineNumber: (NSUInteger) lineNumber columnNumber: (NSUInteger) columnNumber { 27 | if ((self = [super init]) == nil) 28 | return nil; 29 | 30 | _filePath = filePath; 31 | _fileOffset = fileOffset; 32 | _lineNumber = lineNumber; 33 | _columnNumber = columnNumber; 34 | 35 | return self; 36 | 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ObjectDoc/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ObjectDocTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ObjectDocTests/objectdocTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | coop.plausible.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /doctool/DTApplication.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | @interface DTApplication : NSObject 9 | 10 | - (BOOL) run; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /doctool/DTApplication.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "DTApplication.h" 7 | #import "DTConfiguration.h" 8 | #import "DTSourceParser.h" 9 | #import "DTDocSetGenerator.h" 10 | #import "PLClang.h" 11 | #import 12 | 13 | @implementation DTApplication 14 | 15 | - (BOOL) run { 16 | NSError *error = nil; 17 | NSBundle *bundle = [NSBundle mainBundle]; 18 | DTConfiguration *config = nil; 19 | 20 | NSArray *arguments = [[NSProcessInfo processInfo] arguments]; 21 | if ([arguments count] == 1) { 22 | NSLog(@"Usage: doctool --config configfile"); 23 | return NO; 24 | } 25 | 26 | // TODO: Real argument parsing, probably clang compilation database support. 27 | for (NSUInteger i = 1; i < [arguments count]; i++) { 28 | NSString *arg = arguments[i]; 29 | 30 | if ([arg isEqualToString: @"--version"]) { 31 | NSString *version = [bundle infoDictionary][@"CFBundleShortVersionString"]; 32 | NSLog(@"doctool %@\nBased on %@", version, PLClangGetVersionString()); 33 | return YES; 34 | } else if ([arg isEqualToString: @"--config"] && [arguments count] > i+1) { 35 | NSString *configFile = arguments[i+1]; 36 | NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile: configFile]; 37 | config = [[DTConfiguration alloc] initWithPropertyList: plist error: &error]; 38 | i++; 39 | 40 | if (error) { 41 | NSLog(@"Error reading configuration file: %@", error); 42 | return NO; 43 | } 44 | } 45 | } 46 | 47 | if (!config) { 48 | NSLog(@"No configuration file specified."); 49 | return NO; 50 | } 51 | 52 | /* Create a cache directory (for precompiled headers) */ 53 | NSString *baseCachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex: 0]; 54 | NSString *cachePath = [baseCachePath stringByAppendingPathComponent: [bundle bundleIdentifier]]; 55 | if (![[NSFileManager defaultManager] createDirectoryAtPath: cachePath withIntermediateDirectories: YES attributes: nil error: &error]) { 56 | NSLog(@"Error creating cache path %@: %@", cachePath, error); 57 | return NO; 58 | } 59 | 60 | DTSourceParser *parser = [[DTSourceParser alloc] initWithCachePath: cachePath]; 61 | if ([parser parseSourceFiles: [self sourceFilesForConfiguration: config] withCompilerArguments: config.compilerArguments] == NO) 62 | return NO; 63 | 64 | DTLibrary *library = [parser.library filteredLibraryForConfiguration: config]; 65 | 66 | // TODO: Determine how to distribute template files. 67 | // For now assume they are copied alongside the executable. 68 | NSString *templatesDirectory = [bundle pathForResource: @"templates" ofType: @""]; 69 | 70 | NSMutableArray *generators = [NSMutableArray array]; 71 | DTHTMLGenerator *htmlGenerator = [[DTHTMLGenerator alloc] init]; 72 | htmlGenerator.frameworkName = config.frameworkName; 73 | htmlGenerator.showInternalComments = config.showInternalComments; 74 | htmlGenerator.outputDirectory = config.outputPath; 75 | htmlGenerator.templatesDirectory = templatesDirectory; 76 | [generators addObject: htmlGenerator]; 77 | 78 | if ([config.docSetPublisherIdentifier length] > 1) { 79 | DTDocSetGenerator *docSetGenerator = [[DTDocSetGenerator alloc] init]; 80 | docSetGenerator.frameworkName = config.frameworkName; 81 | docSetGenerator.showInternalComments = config.showInternalComments; 82 | docSetGenerator.outputDirectory = config.outputPath; 83 | docSetGenerator.templatesDirectory = templatesDirectory; 84 | docSetGenerator.bundleIdentifier = config.docSetBundleId; 85 | docSetGenerator.bundleName = config.frameworkName; 86 | docSetGenerator.bundleVersion = config.docSetBundleVersion; 87 | docSetGenerator.publisherIdentifier = config.docSetPublisherIdentifier; 88 | docSetGenerator.publisherName = config.docSetPublisherName; 89 | [generators addObject: docSetGenerator]; 90 | } 91 | 92 | for (id generator in generators) { 93 | [generator generateDocumentationForLibrary: library error: &error]; 94 | if (error) { 95 | NSLog(@"Error generating HTML output: %@", error); 96 | return NO; 97 | } 98 | } 99 | 100 | return YES; 101 | } 102 | 103 | /** 104 | * Return an array of source files to parse. 105 | * 106 | * TODO: Consider use of glob(), may want to use regex. 107 | * Consider whether there's existing code or a better way to do this in general, 108 | * may want to specify exclusion of a specific sub-path without applying a global 109 | * pattern. 110 | */ 111 | - (NSSet *) sourceFilesForConfiguration: (DTConfiguration *) config { 112 | NSMutableSet *sourceFiles = [NSMutableSet set]; 113 | NSMutableSet *excludedPaths = [NSMutableSet set]; 114 | NSFileManager *fileManager = [NSFileManager defaultManager]; 115 | 116 | /* Expand any globbed input paths */ 117 | NSMutableArray *searchPaths = [NSMutableArray array]; 118 | for (NSString *path in config.paths) { 119 | glob_t pglob = {}; 120 | glob([path fileSystemRepresentation], GLOB_TILDE, NULL, &pglob); 121 | for (int i = 0; i < pglob.gl_matchc; i++) { 122 | [searchPaths addObject: [NSString stringWithUTF8String: pglob.gl_pathv[i]]]; 123 | } 124 | } 125 | 126 | /* Build the set of exclude paths */ 127 | NSMutableSet *inputDirectories = [NSMutableSet set]; 128 | for (NSString *inputPath in searchPaths) { 129 | BOOL isDirectory = NO; 130 | if ([fileManager fileExistsAtPath: inputPath isDirectory: &isDirectory] == NO) 131 | continue; 132 | 133 | if (isDirectory) { 134 | [inputDirectories addObject: inputPath]; 135 | 136 | NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath: inputPath]; 137 | for (NSString *path in enumerator) { 138 | NSString *fullPath = [inputPath stringByAppendingPathComponent: path]; 139 | [fileManager fileExistsAtPath: fullPath isDirectory: &isDirectory]; 140 | 141 | if (isDirectory) { 142 | [inputDirectories addObject: fullPath]; 143 | } 144 | } 145 | } else { 146 | [inputDirectories addObject: [inputPath stringByDeletingLastPathComponent]]; 147 | } 148 | } 149 | 150 | for (NSString *directory in inputDirectories) { 151 | for (NSString *pattern in config.excludePatterns) { 152 | NSString *fullPattern = [directory stringByAppendingPathComponent: pattern]; 153 | glob_t pglob = {}; 154 | glob([fullPattern fileSystemRepresentation], GLOB_TILDE, NULL, &pglob); 155 | for (int i = 0; i < pglob.gl_matchc; i++) { 156 | [excludedPaths addObject: [NSString stringWithUTF8String: pglob.gl_pathv[i]]]; 157 | } 158 | } 159 | } 160 | 161 | /* Build the array of source files */ 162 | for (NSString *inputPath in searchPaths) { 163 | BOOL isDirectory = NO; 164 | if ([fileManager fileExistsAtPath: inputPath isDirectory: &isDirectory] == NO) 165 | continue; 166 | 167 | if ([excludedPaths containsObject: inputPath]) { 168 | continue; 169 | } 170 | 171 | if (isDirectory == NO && [config.fileTypes containsObject: [inputPath pathExtension]]) { 172 | [sourceFiles addObject: inputPath]; 173 | continue; 174 | } 175 | 176 | NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath: inputPath]; 177 | for (NSString *path in enumerator) { 178 | NSString *fullPath = [inputPath stringByAppendingPathComponent: path]; 179 | [fileManager fileExistsAtPath: fullPath isDirectory: &isDirectory]; 180 | 181 | if ([excludedPaths containsObject: fullPath]) { 182 | if (isDirectory) { 183 | [enumerator skipDescendants]; 184 | } 185 | continue; 186 | } 187 | 188 | if (isDirectory == NO && [config.fileTypes containsObject: [fullPath pathExtension]]) { 189 | [sourceFiles addObject: fullPath]; 190 | } 191 | } 192 | } 193 | 194 | return sourceFiles; 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /doctool/DTConfiguration.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | @interface DTConfiguration : NSObject 9 | 10 | - (instancetype) initWithPropertyList: (NSDictionary *) plist error: (NSError **) error; 11 | 12 | @property(nonatomic, readonly) NSArray *compilerArguments; 13 | @property(nonatomic, readonly) BOOL showUndocumentedEntities; 14 | @property(nonatomic, readonly) BOOL showInternalComments; 15 | 16 | @property(nonatomic, readonly) NSString *frameworkName; 17 | @property(nonatomic, readonly) NSArray *paths; 18 | @property(nonatomic, readonly) NSArray *excludePatterns; 19 | @property(nonatomic, readonly) NSSet *fileTypes; 20 | 21 | @property(nonatomic, readonly) NSString *outputPath; 22 | @property(nonatomic, readonly) BOOL htmlOutputEnabled; 23 | @property(nonatomic, readonly) BOOL docSetOutputEnabled; 24 | 25 | @property(nonatomic, readonly) NSString *docSetBundleId; 26 | @property(nonatomic, readonly) NSString *docSetBundleVersion; 27 | @property(nonatomic, readonly) NSString *docSetPublisherIdentifier; 28 | @property(nonatomic, readonly) NSString *docSetPublisherName; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /doctool/DTConfiguration.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "DTConfiguration.h" 7 | #import "DocTool.h" 8 | #import "PLAdditions.h" 9 | 10 | @implementation DTConfiguration 11 | 12 | - (instancetype) initWithPropertyList: (NSDictionary *) plist error: (NSError **) error { 13 | PLSuperInit(); 14 | 15 | if (error) 16 | *error = nil; 17 | 18 | if (!plist) { 19 | return nil; 20 | } 21 | 22 | _htmlOutputEnabled = YES; 23 | 24 | _paths = plist[@"Paths"]; 25 | if ([_paths count] < 1) { 26 | if (error) { 27 | *error = [self errorWithString: NSLocalizedString(@"No input paths specified.", nil)]; 28 | } 29 | return nil; 30 | } 31 | 32 | _excludePatterns = plist[@"ExcludePatterns"]; 33 | 34 | _fileTypes = [NSSet setWithArray: plist[@"FileTypes"]]; 35 | if ([_fileTypes count] < 1) { 36 | _fileTypes = [NSSet setWithObjects: @"h", @"m", nil]; 37 | } 38 | 39 | _outputPath = plist[@"OutputPath"]; 40 | if ([_outputPath length] < 1) { 41 | if (error) { 42 | *error = [self errorWithString: NSLocalizedString(@"No output path specified.", nil)]; 43 | } 44 | return nil; 45 | } 46 | 47 | _frameworkName = plist[@"Name"]; 48 | if ([_frameworkName length] < 1) { 49 | if (error) { 50 | *error = [self errorWithString: NSLocalizedString(@"No framework name specified.", nil)]; 51 | } 52 | return nil; 53 | } 54 | 55 | _docSetBundleId = plist[@"DocSetBundleId"]; 56 | if ([_docSetBundleId length] > 0) { 57 | _docSetOutputEnabled = YES; 58 | } else { 59 | NSLog(@"No documentation set bundle ID specified, documentation set will not be generated."); 60 | } 61 | 62 | _docSetBundleVersion = plist[@"DocSetBundleVersion"]; 63 | if ([_docSetBundleVersion length] < 1) { 64 | _docSetBundleVersion = @"1.0"; 65 | } 66 | 67 | _docSetPublisherIdentifier = plist[@"DocSetPublisherId"]; 68 | if ([_docSetPublisherIdentifier length] < 1) { 69 | _docSetPublisherIdentifier = [_docSetBundleId stringByDeletingPathExtension]; 70 | } 71 | 72 | _docSetPublisherName = plist[@"DocSetPublisherName"]; 73 | if ([_docSetPublisherName length] < 1) { 74 | _docSetPublisherName = _frameworkName; 75 | } 76 | 77 | _compilerArguments = plist[@"CompilerArguments"]; 78 | if (_compilerArguments == nil) { 79 | _compilerArguments = @[]; 80 | } 81 | 82 | NSNumber *showUndocumentedEntities = plist[@"ShowUndocumentedEntities"]; 83 | if (showUndocumentedEntities) { 84 | _showUndocumentedEntities = [showUndocumentedEntities boolValue]; 85 | } else { 86 | _showUndocumentedEntities = YES; 87 | } 88 | 89 | NSNumber *showInternalComments = plist[@"ShowInternalComments"]; 90 | if (showInternalComments) { 91 | _showInternalComments = [showInternalComments boolValue]; 92 | } else { 93 | _showInternalComments = NO; 94 | } 95 | 96 | return self; 97 | } 98 | 99 | - (NSError *) errorWithString: (NSString *) string { 100 | return [NSError errorWithDomain: DTErrorDomain code: DTErrorConfiguration userInfo: @{ NSLocalizedDescriptionKey: string }]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /doctool/DTDocSetGenerator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "DTHTMLGenerator.h" 8 | 9 | @interface DTDocSetGenerator : DTHTMLGenerator 10 | 11 | @property(nonatomic, copy) NSString *bundleIdentifier; 12 | @property(nonatomic, copy) NSString *bundleName; 13 | @property(nonatomic, copy) NSString *bundleVersion; 14 | @property(nonatomic, copy) NSString *publisherIdentifier; 15 | @property(nonatomic, copy) NSString *publisherName; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /doctool/DTDocSetGenerator.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "DTDocSetGenerator.h" 7 | #import "DocTool.h" 8 | #import "GRMustache.h" 9 | 10 | @implementation DTDocSetGenerator 11 | 12 | - (void) generateDocumentationForLibrary: (DTLibrary *) library error: (NSError **) error { 13 | NSString *docSetOutputDirectory = [[self.outputDirectory stringByAppendingPathComponent: self.bundleIdentifier] stringByAppendingPathExtension: @"docset"]; 14 | self.outputDirectory = [docSetOutputDirectory stringByAppendingPathComponent: @"Contents/Resources/Documents"]; 15 | [super generateDocumentationForLibrary: library error: error]; 16 | 17 | NSString *contentsDirectory = [docSetOutputDirectory stringByAppendingPathComponent: @"Contents"]; 18 | 19 | NSBundle *xcodeBundle = [self selectedXcodeBundle]; 20 | if (!xcodeBundle) { 21 | if (error) { 22 | *error = [NSError errorWithDomain: DTErrorDomain code: DTErrorHTMLOutputGeneration userInfo: @{ 23 | NSLocalizedDescriptionKey: NSLocalizedString(@"Could not locate selected Xcode bundle.", nil) 24 | }]; 25 | } 26 | return; 27 | } 28 | 29 | NSString *minimumXcodeVersion = [self docSetMinimumXcodeVersionForBundle: xcodeBundle]; 30 | if (!minimumXcodeVersion) { 31 | if (error) { 32 | *error = [NSError errorWithDomain: DTErrorDomain code: DTErrorHTMLOutputGeneration userInfo: @{ 33 | NSLocalizedDescriptionKey: NSLocalizedString(@"Could not obtain minimum docset version from selected Xcode bundle.", nil) 34 | }]; 35 | } 36 | } 37 | 38 | NSDictionary *infoPlist = @{ 39 | @"CFBundleIdentifier": self.bundleIdentifier, 40 | @"CFBundleName": self.bundleName, 41 | @"CFBundleVersion": self.bundleVersion, 42 | @"DocSetPublisherIdentifier": self.publisherIdentifier, 43 | @"DocSetPublisherName": self.publisherName, 44 | @"DocSetMinimumXcodeVersion": minimumXcodeVersion 45 | }; 46 | [infoPlist writeToFile: [contentsDirectory stringByAppendingPathComponent: @"Info.plist"] atomically: NO]; 47 | 48 | GRMustacheTemplate *nodesTemplate = [GRMustacheTemplate templateFromContentsOfFile: [self.templatesDirectory stringByAppendingPathComponent: @"Nodes.xml"] error: error]; 49 | NSString *nodesXML = [nodesTemplate renderObject: library error: error]; 50 | if (nodesXML) { 51 | NSString *path = [[contentsDirectory stringByAppendingPathComponent: @"Resources/Nodes"] stringByAppendingPathExtension: @"xml"]; 52 | [nodesXML writeToFile: path atomically: NO encoding: NSUTF8StringEncoding error: error]; 53 | } 54 | 55 | GRMustacheTemplate *tokensTemplate = [GRMustacheTemplate templateFromContentsOfFile: [self.templatesDirectory stringByAppendingPathComponent: @"Tokens.xml"] error: error]; 56 | NSString *tokensXML = [tokensTemplate renderObject: library error: error]; 57 | if (tokensXML) { 58 | NSString *path = [[contentsDirectory stringByAppendingPathComponent: @"Resources/Tokens"] stringByAppendingPathExtension: @"xml"]; 59 | [tokensXML writeToFile: path atomically: NO encoding: NSUTF8StringEncoding error: error]; 60 | } 61 | 62 | [self indexDocSetAtPath: docSetOutputDirectory]; 63 | 64 | // Set the modification date to indicate changes to an existing doc set package directory 65 | [[NSFileManager defaultManager] setAttributes: @{ NSFileModificationDate: [NSDate date] } ofItemAtPath: docSetOutputDirectory error: nil]; 66 | } 67 | 68 | - (void) indexDocSetAtPath: (NSString *) path { 69 | NSTask *task = [NSTask launchedTaskWithLaunchPath: @"/usr/bin/xcrun" arguments: @[@"docsetutil", @"index", path]]; 70 | [task waitUntilExit]; 71 | } 72 | 73 | /** 74 | * Return the minimum Xcode version needed for compatibility with the generted docset. 75 | * 76 | * It is important that this be as correct as possible because docsets are not backward 77 | * compatible and if Xcode loads a docset it does not understand it will likely crash. 78 | * Unfortunately docsetutil does not appear to have any way to query the required Xcode 79 | * version and this information is not published anywhere. As docsetutil itself does not 80 | * have a version number, obtain the major version of the selected Xcode bundle and use 81 | * this as the minimum version. 82 | */ 83 | - (NSString *) docSetMinimumXcodeVersionForBundle: (NSBundle *) bundle { 84 | NSString *xcodeVersion = bundle.infoDictionary[@"CFBundleShortVersionString"]; 85 | int majorVersion = 0; 86 | NSScanner *scanner = [NSScanner scannerWithString: xcodeVersion]; 87 | if ([scanner scanInt:&majorVersion] == NO) 88 | return nil; 89 | 90 | return [NSString stringWithFormat:@"%d.0", majorVersion]; 91 | } 92 | 93 | /** 94 | * Return the currently selected Xcode bundle, as identified by xcode-select --print-path 95 | * 96 | * This is used instead of querying Launch Services because Launch Services will return the 97 | * bundle with the highest version number, while this method will return the bundle used to 98 | * service xcrun invocations. 99 | */ 100 | - (NSBundle *) selectedXcodeBundle { 101 | NSBundle *result = nil; 102 | NSPipe *outputPipe = [NSPipe pipe]; 103 | NSTask *task = [[NSTask alloc] init]; 104 | task.launchPath = @"/usr/bin/xcode-select"; 105 | task.arguments = @[@"--print-path"]; 106 | task.standardInput = [NSPipe pipe]; 107 | task.standardOutput = outputPipe; 108 | task.standardError = [NSPipe pipe]; 109 | [task launch]; 110 | [task waitUntilExit]; 111 | 112 | NSData *pathData = [outputPipe.fileHandleForReading readDataToEndOfFile]; 113 | NSString *path = [[NSString alloc] initWithData: pathData encoding: NSUTF8StringEncoding]; 114 | path = [path stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; 115 | 116 | // Use a URL here because isFilePackageAtPath: is part of AppKit 117 | NSURL *fileURL = [NSURL fileURLWithPath: path]; 118 | NSUInteger count = [[fileURL pathComponents] count]; 119 | if (count == 0) 120 | return result; 121 | 122 | for (NSUInteger i = 0; i < count - 1; i++) { 123 | NSNumber *isPackage = nil; 124 | [fileURL getResourceValue:&isPackage forKey: NSURLIsPackageKey error: nil]; 125 | if ([isPackage boolValue]) { 126 | result = [NSBundle bundleWithURL:fileURL]; 127 | break; 128 | } 129 | fileURL = [fileURL URLByDeletingLastPathComponent]; 130 | } 131 | 132 | return result; 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /doctool/DTDoxygenCommands.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | extern NSString * const DTCommandNameAttention; 9 | extern NSString * const DTCommandNameBrief; 10 | extern NSString * const DTCommandNameDeprecated; 11 | extern NSString * const DTCommandNameEndInternal; 12 | extern NSString * const DTCommandNameInternal; 13 | extern NSString * const DTCommandNameNote; 14 | extern NSString * const DTCommandNameReturn; 15 | extern NSString * const DTCommandNameReturns; 16 | extern NSString * const DTCommandNameWarning; 17 | -------------------------------------------------------------------------------- /doctool/DTDoxygenCommands.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "DTDoxygenCommands.h" 7 | 8 | NSString * const DTCommandNameAttention = @"attention"; 9 | NSString * const DTCommandNameBrief = @"brief"; 10 | NSString * const DTCommandNameDeprecated = @"deprecated"; 11 | NSString * const DTCommandNameEndInternal = @"endinternal"; 12 | NSString * const DTCommandNameInternal = @"internal"; 13 | NSString * const DTCommandNameNote = @"note"; 14 | NSString * const DTCommandNameReturn = @"return"; 15 | NSString * const DTCommandNameReturns = @"returns"; 16 | NSString * const DTCommandNameWarning = @"warning"; 17 | -------------------------------------------------------------------------------- /doctool/DTGenerator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "DTLibrary.h" 8 | 9 | @protocol DTGenerator 10 | 11 | - (void) generateDocumentationForLibrary: (DTLibrary *) library error: (NSError **) error; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /doctool/DTHTMLGenerator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "DTGenerator.h" 8 | 9 | @interface DTHTMLGenerator : NSObject 10 | 11 | @property(nonatomic, copy) NSString *outputDirectory; 12 | @property(nonatomic, copy) NSString *templatesDirectory; 13 | @property(nonatomic, copy) NSString *frameworkName; 14 | @property(nonatomic) BOOL showInternalComments; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /doctool/DTLibrary.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "DTConfiguration.h" 8 | #import "DTNode.h" 9 | 10 | @interface DTLibrary : NSObject 11 | 12 | - (instancetype) initWithNodes: (NSDictionary *) nodes 13 | classes: (NSSet *) classes 14 | protocols: (NSSet *) protocols 15 | categories: (NSSet *) categories 16 | functions: (NSSet *) functions 17 | constants: (NSSet *) constants; 18 | 19 | @property(nonatomic) NSDictionary *nodes; 20 | @property(nonatomic) NSSet *classes; 21 | @property(nonatomic) NSSet *protocols; 22 | @property(nonatomic) NSSet *categories; 23 | @property(nonatomic) NSSet *functions; 24 | @property(nonatomic) NSSet *constants; 25 | 26 | - (instancetype) filteredLibraryForConfiguration: (DTConfiguration *) config; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /doctool/DTLibrary.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "DTLibrary.h" 7 | #import "DTDoxygenCommands.h" 8 | #import "PLAdditions.h" 9 | 10 | @implementation DTLibrary 11 | 12 | - (instancetype) initWithNodes: (NSDictionary *) nodes classes: (NSSet *) classes protocols: (NSSet *) protocols categories: (NSSet *) categories functions: (NSSet *) functions constants: (NSSet *) constants { 13 | PLSuperInit(); 14 | 15 | _nodes = nodes; 16 | _classes = classes; 17 | _protocols = protocols; 18 | _categories = categories; 19 | _functions = functions; 20 | _constants = constants; 21 | 22 | return self; 23 | } 24 | 25 | // TODO: Think on a better way to do this, the unwinding is too complex. Ideally we would not 26 | // add the undocumented nodes at all, but when parsing we don't know if we're only going to 27 | // see declarations or both declarations and implementations, and comments could be attached to 28 | // either. 29 | - (instancetype) filteredLibraryForConfiguration: (DTConfiguration *) config { 30 | if (config.showUndocumentedEntities) { 31 | // If everything is being shown there's no need to filter 32 | return self; 33 | } 34 | 35 | return [[[self class] alloc] initWithNodes: _nodes 36 | classes: [self filterSet: _classes forConfiguration: config] 37 | protocols: [self filterSet: _protocols forConfiguration: config] 38 | categories: [self filterSet: _categories forConfiguration: config] 39 | functions: [self filterSet: _functions forConfiguration: config] 40 | constants: [self filterSet: _constants forConfiguration: config]]; 41 | } 42 | 43 | - (NSSet *) filterSet: (NSSet *) set forConfiguration: (DTConfiguration *) config { 44 | NSMutableSet *filteredSet = [NSMutableSet set]; 45 | 46 | for (DTNode *node in set) { 47 | [self filterNode: node forConfiguration: config]; 48 | 49 | if ([self node: node isVisibleForConfiguration: config] == NO) { 50 | // TOOD: Remove from node lookup as well 51 | } else { 52 | [filteredSet addObject: node]; 53 | } 54 | } 55 | 56 | return filteredSet; 57 | } 58 | 59 | - (NSArray *) filterArray: (NSArray *) array forConfiguration: (DTConfiguration *) config { 60 | NSMutableArray *filteredArray = [NSMutableArray array]; 61 | 62 | for (DTNode *node in array) { 63 | if ([self node: node isVisibleForConfiguration: config] == NO) { 64 | // TOOD: Remove from node lookup as well 65 | } else { 66 | [filteredArray addObject: node]; 67 | } 68 | } 69 | 70 | return filteredArray; 71 | } 72 | 73 | - (void) filterNode: (DTNode *) node forConfiguration: (DTConfiguration *) config { 74 | node.classMethods = [self filterArray: node.classMethods forConfiguration: config]; 75 | node.instanceMethods = [self filterArray: node.instanceMethods forConfiguration: config]; 76 | node.constants = [self filterArray: node.constants forConfiguration: config]; 77 | } 78 | 79 | - (BOOL) node: (DTNode *) node isVisibleForConfiguration: (DTConfiguration *) config { 80 | if (node.comment == nil) 81 | return NO; 82 | 83 | if (config.showInternalComments == NO) { 84 | // Parse enough of the comment to determine if the node has any non-internal content 85 | 86 | BOOL inInternal = NO; 87 | 88 | for (PLClangComment *comment in node.comment.children) { 89 | if (comment.kind != PLClangCommentKindParagraph && !inInternal) 90 | return YES; 91 | 92 | for (PLClangComment *child in comment.children) { 93 | if (child.isWhitespace) 94 | continue; 95 | 96 | switch (child.kind) { 97 | case PLClangCommentKindInlineCommand: 98 | if ([child.commandName isEqualToString: DTCommandNameInternal]) { 99 | inInternal = YES; 100 | } else if ([comment.commandName isEqualToString: DTCommandNameEndInternal]) { 101 | inInternal = NO; 102 | } else if (!inInternal) { 103 | return YES; 104 | } 105 | break; 106 | default: 107 | if (!inInternal) { 108 | return YES; 109 | } 110 | break; 111 | } 112 | } 113 | } 114 | 115 | return NO; 116 | } 117 | 118 | return YES; 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /doctool/DTNode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "PLClangCursor.h" 8 | 9 | @interface DTNode : NSObject 10 | 11 | @property(nonatomic) PLClangCursor *cursor; 12 | @property(nonatomic) PLClangComment *comment; 13 | 14 | @property(nonatomic, copy) NSString *name; 15 | @property(nonatomic, copy) NSString *appleRef; 16 | @property(nonatomic, copy) NSString *briefComment; 17 | @property(nonatomic, copy) NSString *expandedComment; 18 | @property(nonatomic, copy) NSString *fullComment; 19 | @property(nonatomic, copy) NSString *declaration; 20 | @property(nonatomic, copy) NSString *declarationHTML; 21 | @property(nonatomic, copy) NSString *returnValueComment; 22 | @property(nonatomic, getter=isDeprecated) BOOL deprecated; 23 | @property(nonatomic, copy) NSString *deprecationComment; 24 | @property(nonatomic, copy) NSString *path; 25 | 26 | @property(nonatomic) DTNode *superclass; 27 | @property(nonatomic, copy) NSArray *tasks; 28 | @property(nonatomic, copy) NSArray *protocols; 29 | @property(nonatomic, copy) NSArray *properties; 30 | @property(nonatomic, copy) NSArray *classMethods; 31 | @property(nonatomic, copy) NSArray *instanceMethods; 32 | @property(nonatomic, copy) NSArray *implicitMethods; 33 | @property(nonatomic, copy) NSArray *constants; 34 | @property(nonatomic, copy) NSArray *fields; 35 | @property(nonatomic, readonly) NSOrderedSet *allSuperClasses; 36 | @property(nonatomic, readonly) NSOrderedSet *allProtocols; 37 | 38 | @property(nonatomic, copy) NSArray *parameters; 39 | @property(nonatomic, readonly) BOOL isClassMethod; 40 | @property(nonatomic, readonly) BOOL isInstanceMethod; 41 | @property(nonatomic, readonly) BOOL isProperty; 42 | @property(nonatomic, readonly, getter=isRequiredMethod) BOOL requiredMethod; 43 | @property(nonatomic, readonly, getter=isReadOnly) BOOL readOnly; 44 | @property(nonatomic) BOOL isImplicitMethod; 45 | 46 | @property(nonatomic, weak) DTNode *parent; 47 | 48 | /** A UUID string that uniquely identifies the document containing this node. */ 49 | @property(nonatomic, readonly) NSString *UUID; 50 | 51 | /** A node reference number, used for cross-referencing between tokens and nodes within a docset. */ 52 | @property (nonatomic, copy) NSNumber *referenceNumber; 53 | 54 | /** The relative path to the HTML file containing this node. */ 55 | @property(nonatomic, copy) NSString *HTMLPath; 56 | 57 | @property(nonatomic, readonly, getter=isDocumented) BOOL documented; 58 | @property(nonatomic, readonly) BOOL hasCommentedMethods; 59 | @property(nonatomic, readonly) BOOL hasCommentedParameters; 60 | @property(nonatomic, readonly) BOOL hasCommentedConstants; 61 | @property(nonatomic, readonly) BOOL hasCommentedFields; 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /doctool/DTNode.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "DTNode.h" 7 | #import "PLAdditions.h" 8 | 9 | /** 10 | * A documentable node. 11 | */ 12 | @implementation DTNode 13 | 14 | - (id) init { 15 | PLSuperInit(); 16 | 17 | _UUID = [[NSUUID UUID] UUIDString]; 18 | 19 | _briefComment = @""; 20 | _expandedComment = @""; 21 | _fullComment = @""; 22 | _returnValueComment = @""; 23 | 24 | return self; 25 | } 26 | 27 | - (NSOrderedSet *) allSuperclasses { 28 | NSMutableOrderedSet *superclasses = [NSMutableOrderedSet orderedSet]; 29 | DTNode *class = self; 30 | while ((class = class.superclass)) { 31 | [superclasses addObject: class]; 32 | } 33 | 34 | return superclasses; 35 | } 36 | 37 | - (NSOrderedSet *) allProtocols { 38 | NSMutableOrderedSet *protocols = [NSMutableOrderedSet orderedSet]; 39 | DTNode *class = self; 40 | while (class) { 41 | [protocols addObjectsFromArray: class.protocols]; 42 | class = class.superclass; 43 | } 44 | 45 | return protocols; 46 | } 47 | 48 | - (BOOL) isClassMethod { 49 | return (self.cursor.kind == PLClangCursorKindObjCClassMethodDeclaration); 50 | } 51 | 52 | - (BOOL) isInstanceMethod { 53 | return (self.cursor.kind == PLClangCursorKindObjCInstanceMethodDeclaration); 54 | } 55 | 56 | - (BOOL) isProperty { 57 | return (self.cursor.kind == PLClangCursorKindObjCPropertyDeclaration); 58 | } 59 | 60 | - (BOOL) isRequiredMethod { 61 | return (self.parent.cursor.kind == PLClangCursorKindObjCProtocolDeclaration) && !self.cursor.isObjCOptional; 62 | } 63 | 64 | - (BOOL) isReadOnly { 65 | return !!(self.cursor.objCPropertyAttributes & PLClangObjCPropertyAttributeReadOnly); 66 | } 67 | 68 | - (BOOL) hasCommentedMethods { 69 | for (DTNode *node in self.classMethods) { 70 | if (node.documented) 71 | return YES; 72 | } 73 | 74 | for (DTNode *node in self.instanceMethods) { 75 | if (node.documented) 76 | return YES; 77 | } 78 | 79 | for (DTNode *node in self.properties) { 80 | if (node.documented) 81 | return YES; 82 | } 83 | 84 | // TODO: Handle commented implicit methods? 85 | 86 | return NO; 87 | } 88 | 89 | - (BOOL) hasCommentedParameters { 90 | for (DTNode *node in self.parameters) { 91 | if (node.documented) 92 | return YES; 93 | } 94 | 95 | return NO; 96 | } 97 | 98 | - (BOOL) hasCommentedConstants { 99 | for (DTNode *node in self.constants) { 100 | if (node.documented) 101 | return YES; 102 | } 103 | 104 | return NO; 105 | } 106 | 107 | - (BOOL) hasCommentedFields { 108 | for (DTNode *node in self.fields) { 109 | if (node.documented) 110 | return YES; 111 | } 112 | 113 | return NO; 114 | } 115 | 116 | - (BOOL) isDocumented { 117 | return ([self.fullComment length] > 0) || 118 | ([self.briefComment length] > 0) || 119 | self.hasCommentedMethods || 120 | self.hasCommentedParameters || 121 | self.hasCommentedConstants || 122 | self.hasCommentedFields; 123 | } 124 | 125 | - (NSString * ) description { 126 | return [NSString stringWithFormat: @"<%@: %p> %@", [self class], self, self.name]; 127 | } 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /doctool/DTSourceParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "DTLibrary.h" 8 | 9 | @interface DTSourceParser : NSObject 10 | 11 | - (instancetype) initWithCachePath: (NSString *) cachePath; 12 | 13 | @property(nonatomic, readonly) DTLibrary *library; 14 | 15 | - (BOOL) parseSourceFiles: (NSSet *) sourceFiles withCompilerArguments: (NSArray *) compilerArguments; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /doctool/DTTask.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | @interface DTTask : NSObject 9 | 10 | - (instancetype) initWithName: (NSString *) name methods: (NSArray *) methods; 11 | 12 | @property(nonatomic, readonly) NSString *name; 13 | @property(nonatomic, readonly) NSArray *methods; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /doctool/DTTask.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "DTTask.h" 7 | #import "PLAdditions.h" 8 | 9 | @implementation DTTask 10 | 11 | - (instancetype) initWithName: (NSString *) name methods: (NSArray *) methods { 12 | PLSuperInit(); 13 | 14 | _name = name; 15 | _methods = methods; 16 | 17 | return self; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /doctool/DocTool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | 8 | extern NSString * const DTErrorDomain; 9 | 10 | /** 11 | * Error codes in the DTErrorDomain. 12 | */ 13 | typedef NS_ENUM(NSInteger, DTErrorCode) { 14 | /** 15 | * An unknown error occurred. 16 | * 17 | * If this error code is received it is a bug and should be reported. 18 | */ 19 | DTErrorUnknown = 0, 20 | 21 | /** 22 | * A configuration error occurred. 23 | */ 24 | DTErrorConfiguration = 1, 25 | 26 | /** 27 | * An error occurred during generation of HTML output. 28 | */ 29 | DTErrorHTMLOutputGeneration = 2 30 | }; 31 | -------------------------------------------------------------------------------- /doctool/DocTool.m: -------------------------------------------------------------------------------- 1 | #import "DocTool.h" 2 | 3 | /** 4 | * The doctool error domain. 5 | */ 6 | NSString * const DTErrorDomain = @"DTErrorDomain"; 7 | -------------------------------------------------------------------------------- /doctool/doctool-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | coop.plausible.doctool 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | doctool 13 | CFBundleShortVersionString 14 | 0.1 15 | CFBundleVersion 16 | 1 17 | NSHumanReadableCopyright 18 | Copyright © 2013 Landon Fuller. All rights reserved. 19 | 20 | 21 | -------------------------------------------------------------------------------- /doctool/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import 30 | #import "DTApplication.h" 31 | 32 | int main (int argc, const char *argv[]) { 33 | /* Run via dispatch */ 34 | dispatch_async(dispatch_get_main_queue(), ^{ 35 | DTApplication *app = [DTApplication new]; 36 | BOOL result = [app run]; 37 | exit(result ? 0 : 1); 38 | }); 39 | 40 | /* Park in event loop */ 41 | dispatch_main(); 42 | // unreachable 43 | } 44 | -------------------------------------------------------------------------------- /doctool/templates/css/docset.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 13px 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | body[xcode5] .hideInXcode5 { 8 | display: none; 9 | } 10 | 11 | .clear { 12 | clear: both; 13 | } 14 | 15 | a { 16 | color: rgb(51,102,204); 17 | text-decoration: none; 18 | } 19 | 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | 24 | a:active { 25 | text-decoration: none; 26 | } 27 | 28 | a:visited { 29 | text-decoration: underline; 30 | } 31 | 32 | h1 { 33 | margin-top: 0; 34 | margin-bottom: 1.15em; 35 | font-size: 215%; 36 | font-weight: normal; 37 | } 38 | 39 | h2 { 40 | margin-top: 1.75em; 41 | font-size: 187%; 42 | font-weight: normal; 43 | color: #3c4c6c; 44 | padding-bottom: 2px; 45 | } 46 | 47 | h3 { 48 | margin-top: 1.5em; 49 | margin-bottom: .25em; 50 | font-size: 145%; 51 | font-weight: normal; 52 | color: #000; 53 | } 54 | 55 | h5 { 56 | margin: 0.692em 0 0.154em 0; 57 | padding: 0; 58 | font-size: 100%; 59 | color: #000; 60 | } 61 | 62 | table { 63 | font: 13px 'Lucida Grande','Lucida Sans Unicode',Helvetica,Arial,Verdana,sans-serif; 64 | } 65 | 66 | .specbox { 67 | border-top: 1px solid #d6e0e5; 68 | margin-left: 2.5em; 69 | margin-bottom: 2.5em; 70 | } 71 | 72 | .specbox td { 73 | padding: 0.667em; 74 | font-size: 90%; 75 | text-align: left; 76 | vertical-align: top; 77 | border-bottom: 1px solid #d6e0e5; 78 | } 79 | 80 | #superclasses { 81 | margin: 0; 82 | padding: 0; 83 | list-style: none; 84 | } 85 | 86 | #superclasses li { 87 | display: inline; 88 | margin: 0; 89 | } 90 | 91 | #superclasses li:not(:last-of-type)::after { 92 | content: " : "; 93 | } 94 | 95 | #contents { 96 | top: 0px; 97 | bottom: 0px; 98 | border-top: 0px; 99 | left: 0; 100 | right: 0; 101 | z-index: 1; 102 | padding: 0 2em 2em 2em; 103 | overflow: auto; 104 | } 105 | 106 | body[xcode5] #contents { 107 | position: fixed; 108 | } 109 | 110 | .pageTitle { 111 | padding-top: 24px; 112 | } 113 | 114 | #tasks_section h3 { 115 | margin-top: 0.471em; 116 | margin-bottom: .25em; 117 | } 118 | 119 | #tasks_section ul { 120 | padding: 0 0 0.5em 0; 121 | list-style-type: none; 122 | margin: 0 0 0 .5em; 123 | white-space: nowrap; 124 | } 125 | 126 | #tasks_section ul li { 127 | margin: 0.167em 0 0 0; 128 | } 129 | 130 | .task_api_suffix { 131 | color: #996; 132 | font-style: italic; 133 | } 134 | 135 | .deprecated { 136 | color: red; 137 | } 138 | 139 | dl { 140 | margin-top: 0em; 141 | margin-bottom: 0.833em; 142 | } 143 | 144 | dt { 145 | margin-top: 0em; 146 | clear: both; 147 | } 148 | 149 | dd { 150 | margin-left: 1.25em; 151 | margin-top: 0.083em; 152 | margin-bottom: 0.5em; 153 | display: block; 154 | } 155 | 156 | dd p { 157 | margin-top: -0.083em; 158 | margin-bottom: 0.5em; 159 | } 160 | 161 | code, pre { 162 | font-size: 103%; 163 | font-family: Courier, Consolas, monospace; 164 | color: #666; 165 | } 166 | 167 | p { 168 | margin-top: 0; 169 | margin-bottom: .833em; 170 | } 171 | 172 | p.abstract { 173 | margin-top: 1.083em; 174 | margin-bottom: .833em; 175 | } 176 | 177 | .method .declaration { 178 | color: #000; 179 | font: 102% Courier, Consolas, monospace; 180 | margin-top: 1.108em; 181 | margin-bottom: .909em; 182 | } 183 | 184 | .declaration em { 185 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif; 186 | font-size: 100%; 187 | } 188 | 189 | .important { 190 | border: 1px solid #5088C5; 191 | background-color: #f0f3f7; 192 | margin: 1.667em 0 1.75em; 193 | padding: 0 .667em .667em .750em; 194 | } 195 | 196 | .important p { 197 | margin-top: .583em; 198 | margin-bottom: 0; 199 | } 200 | 201 | .note { 202 | border: 1px solid #5088C5; 203 | background-color: #fff; 204 | margin: 1.667em 0 1.75em; 205 | padding: 0 .667em .667em .750em; 206 | } 207 | 208 | .note p { 209 | margin-top: .583em; 210 | margin-bottom: 0; 211 | } 212 | 213 | .warning { 214 | border: 1px solid #000; 215 | background-color: #fff; 216 | margin: 1.667em 0 1.75em; 217 | padding: 0 .667em .667em .750em; 218 | } 219 | 220 | .warning p { 221 | margin-top: .583em; 222 | margin-bottom: 0; 223 | } 224 | 225 | .index_column { 226 | float: left; 227 | width: 33%; 228 | } 229 | 230 | .index_column ol { 231 | list-style-type: none; 232 | margin: 0 0 0 2.5em; 233 | padding: 0 0 1.0em .5em; 234 | list-style-position: outside; 235 | } 236 | 237 | .index_column ol li { 238 | margin: 0.167em 0 0 0; 239 | font-size: 91.67%; 240 | line-height: 1.364em; 241 | } 242 | 243 | .collection_header { 244 | margin-bottom: 2px; 245 | padding-bottom: 3px; 246 | } 247 | 248 | .footer { 249 | margin-top: 2em; 250 | font-size: 80%; 251 | } 252 | -------------------------------------------------------------------------------- /doctool/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{title}} 4 | 5 | 6 | 7 |
8 | 9 |

{{title}}

10 | 11 | {{#classes.count}} 12 |
13 |
    14 |
    Class References
    15 | {{#classes}} 16 |
  1. {{name}}
  2. 17 | {{/classes}} 18 |
19 |
20 | {{/classes.count}} 21 | 22 | {{#protocols.count}} 23 |
24 |
    25 |
    Protocol References
    26 | {{#protocols}} 27 |
  1. {{name}}
  2. 28 | {{/protocols}} 29 |
30 |
31 | {{/protocols.count}} 32 | 33 | {{#includeOtherReferences}} 34 |
35 |
    36 |
    Other References
    37 | {{#constants.count}} 38 |
  1. {{frameworkName}} Constants
  2. 39 | {{/constants.count}} 40 | {{#functions.count}} 41 |
  3. {{frameworkName}} Functions
  4. 42 | {{/functions.count}} 43 |
44 |
45 | {{/includeOtherReferences}} 46 | 47 |

48 | 49 | 55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /doctool/templates/js/docset.js: -------------------------------------------------------------------------------- 1 | function checkForXcode() { 2 | var userAgent = navigator.userAgent; 3 | var xcodeVersion = parseFloat(userAgent.slice(userAgent.indexOf("Xcode/") + 6, userAgent.length)); 4 | if (xcodeVersion >= 5) { 5 | document.body.setAttribute("xcode5", "true"); 6 | } 7 | } 8 | 9 | if (addEventListener !== undefined) { 10 | addEventListener("DOMContentLoaded", checkForXcode); 11 | } 12 | -------------------------------------------------------------------------------- /doctool/templates/nodes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{frameworkName}} Framework Reference 6 | index.html 7 | 8 | {{#classes.count}} 9 | 10 | Reference 11 | Classes/index.html 12 | 13 | {{#classes}} 14 | 15 | {{name}} Class Reference 16 | Classes/{{name}}.html 17 | //apple_ref/doc/uid/{{UUID}} 18 | 19 | {{#fullComment}} 20 | 21 | Overview 22 | {{HTMLPath}} 23 | //apple_ref/doc/uid/{{UUID}}-overview 24 | 25 | {{/fullComment}} 26 | {{#tasks.count}} 27 | 28 | Tasks 29 | {{HTMLPath}} 30 | //apple_ref/doc/uid/{{UUID}}-tasks 31 | 32 | {{/tasks.count}} 33 | {{#properties.count}} 34 | 35 | Properties 36 | {{HTMLPath}} 37 | //apple_ref/doc/uid/{{UUID}}-properties 38 | 39 | {{#properties}} 40 | 41 | {{name}} 42 | {{HTMLPath}} 43 | {{appleRef}} 44 | 45 | {{/properties}} 46 | 47 | 48 | {{/properties.count}} 49 | {{#classMethods.count}} 50 | 51 | Class Methods 52 | {{HTMLPath}} 53 | //apple_ref/doc/uid/{{UUID}}-instance_methods 54 | 55 | {{#classMethods}} 56 | 57 | {{name}} 58 | {{HTMLPath}} 59 | {{appleRef}} 60 | 61 | {{/classMethods}} 62 | 63 | 64 | {{/classMethods.count}} 65 | {{#instanceMethods.count}} 66 | 67 | Instance Methods 68 | {{HTMLPath}} 69 | //apple_ref/doc/uid/{{UUID}}-instance_methods 70 | 71 | {{#instanceMethods}} 72 | 73 | {{name}} 74 | {{HTMLPath}} 75 | {{appleRef}} 76 | 77 | {{/instanceMethods}} 78 | 79 | 80 | {{/instanceMethods.count}} 81 | {{#.constants.count}} 82 | 83 | Constants 84 | {{HTMLPath}} 85 | //apple_ref/doc/uid/{{UUID}}-constants 86 | 87 | {{#constants}} 88 | 89 | {{name}} 90 | {{HTMLPath}} 91 | {{appleRef}} 92 | 93 | {{/constants}} 94 | 95 | 96 | {{/.constants.count}} 97 | 98 | 99 | {{/classes}} 100 | 101 | 102 | {{/classes.count}} 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /doctool/templates/objc_container.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{title}} 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 |

{{title}}

13 | 14 |
15 | 16 | 17 | {{#allSuperclasses.count}} 18 | 19 | 20 | 21 | 22 | {{/allSuperclasses.count}} 23 | {{#allProtocols.count}} 24 | 25 | 26 | 32 | 33 | {{/allProtocols.count}} 34 | {{#frameworkName}} 35 | 36 | 37 | 38 | 39 | {{/frameworkName}} 40 | {{#path}} 41 | 42 | 43 | 44 | 45 | {{/path}} 46 | 47 |
Inherits from
    {{#allSuperclasses}}
  • {{name}}
  • {{/allSuperclasses}}
Conforms to 27 | {{#protocols}}{{#.HTMLPath}}{{/.HTMLPath}}{{.}}{{#.HTMLPath}}{{/.HTMLPath}}
{{/protocols}} 28 | {{#allSuperclasses}} 29 | {{#protocols}}{{.}} ({{name}})
{{/protocols}} 30 | {{/allSuperclasses}} 31 |
Framework{{.}}
Declared in{{.lastPathComponent}}
48 |
49 | 50 | {{#fullComment}} 51 |
52 | 53 |

Overview

54 | {{{.}}} 55 |
56 | {{/fullComment}} 57 | 58 | {{#tasks.count}} 59 |
60 | 61 |

Tasks

62 | 63 | {{#tasks}} 64 |

{{name}}

65 |
    66 | {{#methods}} 67 | {{#isProperty}} 68 |
  • 69 |   {{name}} 70 |  property{{#deprecated}}  Deprecated{{/deprecated}} 71 |
  • 72 | {{/isProperty}} 73 | {{#isClassMethod}} 74 |
  • + {{name}}{{#requiredMethod}}  required method{{/requiredMethod}}{{#deprecated}}  Deprecated{{/deprecated}}
  • 75 | {{/isClassMethod}} 76 | {{#isInstanceMethod}} 77 |
  • - {{name}}{{#requiredMethod}}  required method{{/requiredMethod}}{{#deprecated}}  Deprecated{{/deprecated}}
  • 78 | {{/isInstanceMethod}} 79 | {{/methods}} 80 |
81 | {{/tasks}} 82 |
83 | {{/tasks.count}} 84 | 85 | {{#properties.count}} 86 | 87 |

Properties

88 | 89 |
90 | {{#properties}} 91 | {{> objc_node}} 92 | {{/properties}} 93 |
94 | {{/properties.count}} 95 | 96 | {{#classMethods.count}} 97 | 98 |

Class Methods

99 | 100 |
101 | {{#classMethods}} 102 | {{> objc_node}} 103 | {{/classMethods}} 104 |
105 | {{/classMethods.count}} 106 | 107 | {{#instanceMethods.count}} 108 | 109 |

Instance Methods

110 | 111 |
112 | {{#instanceMethods}} 113 | {{> objc_node}} 114 | {{/instanceMethods}} 115 |
116 | {{/instanceMethods.count}} 117 | 118 | {{#constants.count}} 119 | 120 |

Constants

121 | 122 |
123 | {{#constants}} 124 | {{> objc_node}} 125 | {{/constants}} 126 |
127 | {{/constants.count}} 128 | 129 | {{#functions.count}} 130 | 131 |

Functions

132 | 133 |
134 | {{#functions}} 135 | {{> objc_node}} 136 | {{/functions}} 137 |
138 | {{/functions.count}} 139 | 140 | 146 |
147 | 148 | 149 | -------------------------------------------------------------------------------- /doctool/templates/objc_node.html: -------------------------------------------------------------------------------- 1 | 2 |

{{name}}

3 | {{#briefComment}} 4 |

{{{.}}}{{#readOnly}} (read-only){{/readOnly}}{{#deprecated}} (Deprecated.{{#deprecationComment}} {{.}}{{/deprecationComment}}){{/deprecated}}

5 | {{/briefComment}} 6 |
{{{declarationHTML}}}{{^declarationHTML}}
{{declaration}}
{{/declarationHTML}}
7 | {{#hasCommentedConstants}} 8 |
9 |
Constants
10 |
11 | {{#constants}} 12 | {{#fullComment}} 13 |
14 | 15 | {{name}} 16 |
17 |
18 | {{{.}}} 19 | {{#deprecated}}

Deprecated.{{#deprecationComment}} {{.}}{{/deprecationComment}}

{{/deprecated}} 20 | {{#path}}

Declared in {{.lastPathComponent}}.

{{/path}} 21 |
22 | {{/fullComment}} 23 | {{/constants}} 24 |
25 |
26 | {{/hasCommentedConstants}} 27 | {{#hasCommentedFields}} 28 |
29 |
Fields
30 |
31 | {{#fields}} 32 | {{#fullComment}} 33 |
34 | {{name}} 35 |
36 |
37 | {{{.}}} 38 | {{#deprecated}}

Deprecated.{{#deprecationComment}} {{.}}{{/deprecationComment}}

{{/deprecated}} 39 |
40 | {{/fullComment}} 41 | {{/fields}} 42 |
43 |
44 | {{/hasCommentedFields}} 45 | {{#hasCommentedParameters}} 46 |
47 |
Parameters
48 |
49 | {{#parameters}} 50 | {{#fullComment}} 51 |
52 | {{name}} 53 |
54 |
55 | {{{.}}} 56 |
57 | {{/fullComment}} 58 | {{/parameters}} 59 |
60 |
61 | {{/hasCommentedParameters}} 62 | {{#returnValueComment}} 63 |
64 |
Return Value
65 |

{{{.}}}

66 |
67 | {{/returnValueComment}} 68 | {{#expandedComment}} 69 |
70 |
Discussion
71 | {{{.}}} 72 |
73 | {{/expandedComment}} 74 |
75 |
Declared In
76 | {{path.lastPathComponent}} 77 |
-------------------------------------------------------------------------------- /doctool/templates/token.xml: -------------------------------------------------------------------------------- 1 | 2 | {{appleRef}} 3 | {{HTMLPath}} 4 | {{appleRef}} 5 | {{briefComment}} 6 | 7 | 1.0 8 | 9 | 10 | {{path.lastPathComponent}} 11 | {{frameworkName}} 12 | 13 | {{#referenceNumber}}{{/referenceNumber}} 14 | 15 | -------------------------------------------------------------------------------- /doctool/templates/tokens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{#classes}} 4 | {{> token}} 5 | 6 | {{#properties}}{{> token}} 7 | {{/properties}} 8 | 9 | {{#classMethods}} 10 | {{> token}} 11 | {{/classMethods}} 12 | 13 | {{#instanceMethods}} 14 | {{> token}} 15 | {{/instanceMethods}} 16 | 17 | {{#.constants}} 18 | {{> token}} 19 | {{#.constants}} 20 | {{> token}} 21 | {{/.constants}} 22 | {{/.constants}} 23 | 24 | {{/classes}} 25 | 26 | {{#constants}} 27 | {{> token}} 28 | {{#.constants}} 29 | {{> token}} 30 | {{/.constants}} 31 | {{/constants}} 32 | 33 | --------------------------------------------------------------------------------