├── .codecov.yml
├── .gitignore
├── .swiftlint.yml
├── .travis.yml
├── CHANGELOG.md
├── Gemfile
├── Gemfile.lock
├── IBAnalyzer.podspec
├── IBAnalyzer.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── IBAnalyzer.xcscheme
├── IBAnalyzer.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── IBAnalyzer
├── Analyzers
│ ├── Analyzer.swift
│ └── ConnectionAnalyzer.swift
├── Helpers
│ └── DirectoryContentsEnumerator.swift
├── Info.plist
├── Models
│ ├── Class.swift
│ └── Nib.swift
├── Parsers
│ ├── NibParser.swift
│ ├── SwiftParser.swift
│ └── UIKitOutlets.swift
├── Runner.swift
└── main.swift
├── IBAnalyzerTests
├── ConnectionAnalyzerTests.swift
├── DirectoryContentsEnumeratorTests.swift
├── Examples
│ └── Example.storyboard
├── Info.plist
├── NibParserTests.swift
├── RunnerTests.swift
├── Stubs.swift
└── SwiftParserTests.swift
├── LICENSE
├── Podfile
├── Podfile.lock
├── Pods
├── Manifest.lock
├── Manifest.lock-e
├── Pods.xcodeproj
│ ├── project.pbxproj
│ └── project.pbxproj-e
├── SWXMLHash
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ ├── SWXMLHash+TypeConversion.swift
│ │ └── SWXMLHash.swift
├── SourceKittenFramework
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ └── SourceKittenFramework
│ │ ├── Clang+SourceKitten.swift
│ │ ├── ClangTranslationUnit.swift
│ │ ├── CodeCompletionItem.swift
│ │ ├── Dictionary+Merge.swift
│ │ ├── Documentation.swift
│ │ ├── File.swift
│ │ ├── JSONOutput.swift
│ │ ├── Language.swift
│ │ ├── LinuxCompatibility.swift
│ │ ├── Module.swift
│ │ ├── ObjCDeclarationKind.swift
│ │ ├── OffsetMap.swift
│ │ ├── Parameter.swift
│ │ ├── Request.swift
│ │ ├── SourceDeclaration.swift
│ │ ├── SourceLocation.swift
│ │ ├── StatementKind.swift
│ │ ├── String+SourceKitten.swift
│ │ ├── Structure.swift
│ │ ├── SwiftDeclarationKind.swift
│ │ ├── SwiftDocKey.swift
│ │ ├── SwiftDocs.swift
│ │ ├── SwiftLangSyntax.swift
│ │ ├── SyntaxKind.swift
│ │ ├── SyntaxMap.swift
│ │ ├── SyntaxToken.swift
│ │ ├── Text.swift
│ │ ├── Version.swift
│ │ ├── Xcode.swift
│ │ ├── clang-c
│ │ ├── BuildSystem.h
│ │ ├── CXCompilationDatabase.h
│ │ ├── CXErrorCode.h
│ │ ├── CXString.h
│ │ ├── Documentation.h
│ │ ├── Index.h
│ │ └── Platform.h
│ │ ├── library_wrapper.swift
│ │ ├── library_wrapper_CXString.swift
│ │ ├── library_wrapper_Documentation.swift
│ │ ├── library_wrapper_Index.swift
│ │ ├── library_wrapper_sourcekitd.swift
│ │ └── sourcekitd.h
├── Target Support Files
│ ├── Pods-IBAnalyzer-IBAnalyzerTests
│ │ ├── Info.plist
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests-acknowledgements.markdown
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests-acknowledgements.plist
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests-dummy.m
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests-frameworks.sh
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests-resources.sh
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests-umbrella.h
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests.debug.xcconfig
│ │ ├── Pods-IBAnalyzer-IBAnalyzerTests.modulemap
│ │ └── Pods-IBAnalyzer-IBAnalyzerTests.release.xcconfig
│ ├── Pods-IBAnalyzer
│ │ ├── Info.plist
│ │ ├── Pods-IBAnalyzer-acknowledgements.markdown
│ │ ├── Pods-IBAnalyzer-acknowledgements.plist
│ │ ├── Pods-IBAnalyzer-dummy.m
│ │ ├── Pods-IBAnalyzer-frameworks.sh
│ │ ├── Pods-IBAnalyzer-resources.sh
│ │ ├── Pods-IBAnalyzer-umbrella.h
│ │ ├── Pods-IBAnalyzer.debug.xcconfig
│ │ ├── Pods-IBAnalyzer.modulemap
│ │ └── Pods-IBAnalyzer.release.xcconfig
│ ├── SWXMLHash
│ │ ├── Info.plist
│ │ ├── SWXMLHash-dummy.m
│ │ ├── SWXMLHash-prefix.pch
│ │ ├── SWXMLHash-umbrella.h
│ │ ├── SWXMLHash.modulemap
│ │ └── SWXMLHash.xcconfig
│ ├── SourceKittenFramework
│ │ ├── Info.plist
│ │ ├── SourceKittenFramework-dummy.m
│ │ ├── SourceKittenFramework-prefix.pch
│ │ ├── SourceKittenFramework-umbrella.h
│ │ ├── SourceKittenFramework.modulemap
│ │ └── SourceKittenFramework.xcconfig
│ └── Yams
│ │ ├── Info.plist
│ │ ├── Yams-dummy.m
│ │ ├── Yams-prefix.pch
│ │ ├── Yams-umbrella.h
│ │ ├── Yams.modulemap
│ │ └── Yams.xcconfig
└── Yams
│ ├── LICENSE
│ ├── README.md
│ └── Sources
│ ├── CYaml
│ ├── include
│ │ ├── CYaml.h
│ │ └── yaml.h
│ └── src
│ │ ├── api.c
│ │ ├── emitter.c
│ │ ├── parser.c
│ │ ├── reader.c
│ │ ├── scanner.c
│ │ ├── writer.c
│ │ └── yaml_private.h
│ └── Yams
│ ├── Constructor.swift
│ ├── Decoder.swift
│ ├── Emitter.swift
│ ├── Encoder.swift
│ ├── Mark.swift
│ ├── Node.Mapping.swift
│ ├── Node.Scalar.swift
│ ├── Node.Sequence.swift
│ ├── Node.swift
│ ├── Parser.swift
│ ├── Representer.swift
│ ├── Resolver.swift
│ ├── String+Yams.swift
│ ├── Tag.swift
│ ├── YamlError.swift
│ └── Yams.h
├── README.md
├── Rakefile
├── Resources
├── unnecessary-action@2x.png
└── unnecessary-outlet@2x.png
└── bin
└── ibanalyzer
/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | ignore:
3 | - Pods/*
4 | status:
5 | patch: false
6 | changes: false
7 | project:
8 | default:
9 | target: 75
10 | comment: false
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | bin/IBAnalyzer.app
8 | DerivedData/
9 |
10 | ## Various settings
11 | *.pbxuser
12 | !default.pbxuser
13 | *.mode1v3
14 | !default.mode1v3
15 | *.mode2v3
16 | !default.mode2v3
17 | *.perspectivev3
18 | !default.perspectivev3
19 | xcuserdata/
20 |
21 | ## Other
22 | *.moved-aside
23 | *.xcuserstate
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | .build/
40 |
41 | # CocoaPods
42 | #
43 | # We recommend against adding the Pods directory to your .gitignore. However
44 | # you should judge for yourself, the pros and cons are mentioned at:
45 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
46 | #
47 | # Pods/
48 | Pods/SwiftLint/
49 |
50 | # Carthage
51 | #
52 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
53 | # Carthage/Checkouts
54 |
55 | Carthage/Build
56 |
57 | # fastlane
58 | #
59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60 | # screenshots whenever they are needed.
61 | # For more information about the recommended setup visit:
62 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
63 |
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 |
69 | .apitoken
70 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | excluded: # paths to ignore during linting. overridden byincluded.
2 | - Pods
3 | disabled_rules:
4 | - line_length
5 |
6 | # configurable rules can be customized from this configuration file
7 | # binary rules can set their severity level
8 | shorthand_operator: warning # implicitly
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode9.2
3 | script:
4 | - xcodebuild -scheme IBAnalyzer -workspace IBAnalyzer.xcworkspace
5 | - xcodebuild test -scheme IBAnalyzer -workspace IBAnalyzer.xcworkspace
6 | after_success:
7 | - bash <(curl -s https://codecov.io/bash) -J 'IBAnalyzer'
8 |
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # IBAnalyzer CHANGELOG
2 |
3 | ---
4 |
5 | ## 0.3.0
6 |
7 | - Swift 4.1 compatibility.
8 |
9 | ## 0.2.1
10 |
11 | - Improved README.
12 | - Replaces errors with warnings.
13 |
14 | ## 0.2.0
15 |
16 | - Build phase integration through CocoaPods.
17 |
18 | ## 0.1.1
19 |
20 | - Fixes relative paths passed to CLI not working correctly.
21 |
22 | ## 0.1.0
23 |
24 | Initial release.
25 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'cocoapods', '1.5.3'
4 | gem 'xcpretty', '0.2.4'
5 | gem 'rake', '12.3.1'
6 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.0)
5 | activesupport (4.2.10)
6 | i18n (~> 0.7)
7 | minitest (~> 5.1)
8 | thread_safe (~> 0.3, >= 0.3.4)
9 | tzinfo (~> 1.1)
10 | atomos (0.1.2)
11 | claide (1.0.2)
12 | cocoapods (1.5.3)
13 | activesupport (>= 4.0.2, < 5)
14 | claide (>= 1.0.2, < 2.0)
15 | cocoapods-core (= 1.5.3)
16 | cocoapods-deintegrate (>= 1.0.2, < 2.0)
17 | cocoapods-downloader (>= 1.2.0, < 2.0)
18 | cocoapods-plugins (>= 1.0.0, < 2.0)
19 | cocoapods-search (>= 1.0.0, < 2.0)
20 | cocoapods-stats (>= 1.0.0, < 2.0)
21 | cocoapods-trunk (>= 1.3.0, < 2.0)
22 | cocoapods-try (>= 1.1.0, < 2.0)
23 | colored2 (~> 3.1)
24 | escape (~> 0.0.4)
25 | fourflusher (~> 2.0.1)
26 | gh_inspector (~> 1.0)
27 | molinillo (~> 0.6.5)
28 | nap (~> 1.0)
29 | ruby-macho (~> 1.1)
30 | xcodeproj (>= 1.5.7, < 2.0)
31 | cocoapods-core (1.5.3)
32 | activesupport (>= 4.0.2, < 6)
33 | fuzzy_match (~> 2.0.4)
34 | nap (~> 1.0)
35 | cocoapods-deintegrate (1.0.2)
36 | cocoapods-downloader (1.2.1)
37 | cocoapods-plugins (1.0.0)
38 | nap
39 | cocoapods-search (1.0.0)
40 | cocoapods-stats (1.0.0)
41 | cocoapods-trunk (1.3.0)
42 | nap (>= 0.8, < 2.0)
43 | netrc (~> 0.11)
44 | cocoapods-try (1.1.0)
45 | colored2 (3.1.2)
46 | concurrent-ruby (1.0.5)
47 | escape (0.0.4)
48 | fourflusher (2.0.1)
49 | fuzzy_match (2.0.4)
50 | gh_inspector (1.1.3)
51 | i18n (0.9.5)
52 | concurrent-ruby (~> 1.0)
53 | minitest (5.11.3)
54 | molinillo (0.6.5)
55 | nanaimo (0.2.5)
56 | nap (1.1.0)
57 | netrc (0.11.0)
58 | rake (12.3.1)
59 | rouge (1.11.1)
60 | ruby-macho (1.2.0)
61 | thread_safe (0.3.6)
62 | tzinfo (1.2.5)
63 | thread_safe (~> 0.1)
64 | xcodeproj (1.5.9)
65 | CFPropertyList (>= 2.3.3, < 4.0)
66 | atomos (~> 0.1.2)
67 | claide (>= 1.0.2, < 2.0)
68 | colored2 (~> 3.1)
69 | nanaimo (~> 0.2.5)
70 | xcpretty (0.2.4)
71 | rouge (~> 1.8)
72 |
73 | PLATFORMS
74 | ruby
75 |
76 | DEPENDENCIES
77 | cocoapods (= 1.5.3)
78 | rake (= 12.3.1)
79 | xcpretty (= 0.2.4)
80 |
81 | BUNDLED WITH
82 | 1.16.1
83 |
--------------------------------------------------------------------------------
/IBAnalyzer.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "IBAnalyzer"
4 | s.version = "0.3.0"
5 | s.summary = "Tool for finding xib and storyboard-related issues at the build time."
6 |
7 | s.homepage = "https://github.com/fastred/IBAnalyzer"
8 | s.license = "MIT"
9 | s.author = { "Arkadiusz Holko" => "fastred@fastred.org" }
10 | s.social_media_url = "https://twitter.com/arekholko"
11 |
12 | s.source = { :http => "https://github.com/fastred/IBAnalyzer/releases/download/#{s.version}/ibanalyzer-#{s.version}.zip" }
13 | s.preserve_paths = '*'
14 |
15 | end
16 |
--------------------------------------------------------------------------------
/IBAnalyzer.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IBAnalyzer.xcodeproj/xcshareddata/xcschemes/IBAnalyzer.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
35 |
41 |
42 |
43 |
44 |
45 |
51 |
52 |
53 |
54 |
55 |
56 |
67 |
69 |
75 |
76 |
77 |
78 |
81 |
82 |
83 |
84 |
88 |
89 |
90 |
91 |
92 |
93 |
99 |
101 |
107 |
108 |
109 |
110 |
112 |
113 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/IBAnalyzer.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/IBAnalyzer.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/IBAnalyzer/Analyzers/Analyzer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Analyzer.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 29/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct AnalyzerConfiguration {
12 | let classNameToNibMap: [String: Nib]
13 | let classNameToClassMap: [String: Class]
14 | let uiKitClassNameToClassMap: [String: Class]
15 |
16 | init(classNameToNibMap: [String: Nib],
17 | classNameToClassMap: [String: Class],
18 | uiKitClassNameToClassMap: [String: Class] = uiKitClassNameToClass()) {
19 | self.classNameToNibMap = classNameToNibMap
20 | self.classNameToClassMap = classNameToClassMap
21 | self.uiKitClassNameToClassMap = uiKitClassNameToClassMap
22 | }
23 | }
24 |
25 | protocol Issue: CustomStringConvertible {
26 | var isSeriousViolation: Bool { get }
27 | }
28 |
29 | protocol Analyzer {
30 | func issues(for configuration: AnalyzerConfiguration) -> [Issue]
31 | }
32 |
--------------------------------------------------------------------------------
/IBAnalyzer/Helpers/DirectoryContentsEnumerator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DirectoryContentsEnumerator.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 24-12-16.
6 | // Copyright © 2016 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | protocol DirectoryContentsEnumeratorType {
12 | func files(at url: URL, fileManager: FileManager) throws -> [URL]
13 | }
14 |
15 | struct DirectoryContentsEnumerator: DirectoryContentsEnumeratorType {
16 |
17 | func files(at url: URL, fileManager: FileManager = FileManager.default) throws -> [URL] {
18 | guard let enumerator = fileManager.enumerator(at: url,
19 | includingPropertiesForKeys: [],
20 | options: [],
21 | errorHandler: nil) else {
22 | return []
23 | }
24 |
25 | var fileURLs: [URL] = []
26 |
27 | for case let fileURL as URL in enumerator {
28 | let resourceValues = try fileURL.resolvingSymlinksInPath()
29 | .resourceValues(forKeys: [.pathKey, .isDirectoryKey])
30 | if let isDirectory = resourceValues.isDirectory,
31 | !isDirectory,
32 | let path = resourceValues.path {
33 |
34 | fileURLs.append(URL(fileURLWithPath: path))
35 | }
36 | }
37 |
38 | return fileURLs
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/IBAnalyzer/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | Copyright © 2016 Arkadiusz Holko. All rights reserved.
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/IBAnalyzer/Models/Class.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Class.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 29/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Class {
12 | var outlets: [Declaration]
13 | var actions: [Declaration]
14 | var inherited: [String]
15 | }
16 |
17 | extension Class: Equatable {
18 | public static func == (lhs: Class, rhs: Class) -> Bool {
19 | return lhs.outlets == rhs.outlets
20 | && lhs.actions == rhs.actions
21 | && lhs.inherited == rhs.inherited
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/IBAnalyzer/Models/Nib.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Nib.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 29/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Nib {
12 | var outlets: [Declaration]
13 | var actions: [Declaration]
14 | }
15 |
16 | extension Nib: Equatable {
17 | public static func == (lhs: Nib, rhs: Nib) -> Bool {
18 | return lhs.outlets == rhs.outlets && lhs.actions == rhs.actions
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/IBAnalyzer/Parsers/NibParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NibParser.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 24-12-16.
6 | // Copyright © 2016 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | protocol NibParserType {
12 | func mappingForFile(at url: URL) throws -> [String: Nib]
13 | }
14 |
15 | class NibParser: NibParserType {
16 | func mappingForFile(at url: URL) throws -> [String: Nib] {
17 | let parser = XMLParser(data: try Data(contentsOf: url))
18 |
19 | let delegate = ParserDelegate()
20 | delegate.url = url
21 | parser.delegate = delegate
22 | parser.parse()
23 |
24 | return delegate.classNameToNibMap
25 | }
26 | }
27 |
28 | // Thanks to SwiftGen for the inspiration :)
29 |
30 | private class ParserDelegate: NSObject, XMLParserDelegate {
31 |
32 | private struct Element {
33 | let tag: String
34 | let customClassName: String?
35 | }
36 |
37 | var url: URL!
38 | var inObjects = false
39 | var inConnections = false
40 | private var stack: [Element] = []
41 |
42 | var classNameToNibMap: [String: Nib] = [:]
43 | var idToCustomClassMap: [String: String] = [:]
44 |
45 | @objc func parser(_ parser: XMLParser, didStartElement elementName: String,
46 | namespaceURI: String?, qualifiedName qName: String?,
47 | attributes attributeDict: [String: String]) {
48 |
49 | switch elementName {
50 | case "objects":
51 | inObjects = true
52 | stack = []
53 | case "connections":
54 | inConnections = true
55 | case "outlet" where inConnections, "outletCollection" where inConnections:
56 | guard let property = attributeDict["property"],
57 | let customClassName = stack.last?.customClassName else {
58 | break
59 | }
60 |
61 | let outlet = Declaration(name: property, line: parser.lineNumber, column: parser.columnNumber, url: url)
62 | classNameToNibMap[customClassName]?.outlets.append(outlet)
63 | case "action" where inConnections:
64 | guard let selector = attributeDict["selector"],
65 | let destination = attributeDict["destination"],
66 | let customClassName = idToCustomClassMap[destination] else {
67 | break
68 | }
69 | let action = Declaration(name: selector, line: parser.lineNumber, column: parser.columnNumber, url: url)
70 | classNameToNibMap[customClassName]?.actions.append(action)
71 | case let tag where (inObjects && tag != "viewControllerPlaceholder"):
72 | // swiftlint:disable identifier_name superfluous_disable_command
73 | let customClass = attributeDict["customClass"]
74 | let id = attributeDict["id"]
75 | stack.append(Element(tag: tag, customClassName: customClass))
76 |
77 | if let customClass = customClass, let id = id {
78 | idToCustomClassMap[id] = customClass
79 | classNameToNibMap[customClass] = Nib(outlets: [], actions: [])
80 | }
81 | // swiftlint:disable identifier_name superfluous_disable_command
82 | default:
83 | break
84 | }
85 | }
86 |
87 | @objc func parser(_ parser: XMLParser, didEndElement elementName: String,
88 | namespaceURI: String?, qualifiedName qName: String?) {
89 | switch elementName {
90 | case "objects":
91 | inObjects = false
92 | assert(stack.count == 0)
93 | case "connections":
94 | inConnections = false
95 | case "outlet", "outletCollection", "action":
96 | break
97 | case let tag where (inObjects && tag != "viewControllerPlaceholder"):
98 | stack.removeLast()
99 | default:
100 | break
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/IBAnalyzer/Parsers/SwiftParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftParser.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 26-12-16.
6 | // Copyright © 2016 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SourceKittenFramework
11 |
12 | protocol SwiftParserType {
13 | func mappingForFile(at url: URL, result: inout [String: Class]) throws
14 | func mappingForContents(_ contents: String, result: inout [String: Class]) throws
15 | }
16 |
17 | enum SwiftParserError: Error {
18 | case incorrectPath(path: String)
19 | }
20 |
21 | class SwiftParser: SwiftParserType {
22 | func mappingForFile(at url: URL, result: inout [String: Class]) throws {
23 | if let file = File(path: url.path) {
24 | return try mapping(for: file, result: &result)
25 | } else {
26 | throw SwiftParserError.incorrectPath(path: url.path)
27 | }
28 | }
29 |
30 | func mappingForContents(_ contents: String, result: inout [String: Class]) throws {
31 | return try mapping(for: File(contents: contents), result: &result)
32 | }
33 |
34 | private func mapping(for file: File, result: inout [String: Class]) throws {
35 | let fileStructure = try Structure(file: file)
36 | let dictionary = fileStructure.dictionary
37 |
38 | parseSubstructure(dictionary.substructure, result: &result, file: file)
39 | }
40 |
41 | private func parseSubstructure(_ substructure: [[String: SourceKitRepresentable]],
42 | result: inout [String: Class],
43 | file: File) {
44 | for structure in substructure {
45 | var outlets: [Declaration] = []
46 | var actions: [Declaration] = []
47 |
48 | if let kind = structure["key.kind"] as? String,
49 | let name = structure["key.name"] as? String,
50 | kind == "source.lang.swift.decl.class" || kind == "source.lang.swift.decl.extension" {
51 |
52 | for insideStructure in structure.substructure {
53 | if let attributes = insideStructure["key.attributes"] as? [[String: AnyObject]],
54 | let propertyName = insideStructure["key.name"] as? String {
55 |
56 | let isOutlet = attributes.contains { dict -> Bool in
57 | return dict.values.contains(where: { $0 as? String == "source.decl.attribute.iboutlet" })
58 | }
59 |
60 | if isOutlet, let nameOffset64 = insideStructure["key.nameoffset"] as? Int64 {
61 | outlets.append(Declaration(name: propertyName, file: file, offset: nameOffset64, isOptional: insideStructure.isOptional))
62 | }
63 |
64 | let isIBAction = attributes.contains { dict -> Bool in
65 | return dict.values.contains(where: { $0 as? String == "source.decl.attribute.ibaction" })
66 | }
67 |
68 | if isIBAction, let selectorName = insideStructure["key.selector_name"] as? String,
69 | let nameOffset64 = insideStructure["key.nameoffset"] as? Int64 {
70 | actions.append(Declaration(name: selectorName, file: file, offset: nameOffset64))
71 | }
72 | }
73 | }
74 |
75 | parseSubstructure(structure.substructure, result: &result, file: file)
76 | let inherited = extractedInheritedTypes(structure: structure)
77 | let existing = result[name]
78 |
79 | // appending needed because of extensions
80 | result[name] = Class(outlets: outlets + (existing?.outlets ?? []),
81 | actions: actions + (existing?.actions ?? []),
82 | inherited: inherited + (existing?.inherited ?? []))
83 | }
84 | }
85 | }
86 |
87 | private func extractedInheritedTypes(structure: [String: SourceKitRepresentable]) -> [String] {
88 | guard let inherited = structure["key.inheritedtypes"] as? [[String: String]] else {
89 | return []
90 | }
91 |
92 | let result = inherited.map { $0["key.name"] }.flatMap { $0 }
93 | return result
94 | }
95 | }
96 |
97 | private extension Dictionary where Key: ExpressibleByStringLiteral {
98 | var substructure: [[String: SourceKitRepresentable]] {
99 | let substructure = self["key.substructure"] as? [SourceKitRepresentable] ?? []
100 | return substructure.flatMap { $0 as? [String: SourceKitRepresentable] }
101 | }
102 |
103 | var isOptional: Bool {
104 | if let typename = self["key.typename"] as? String,
105 | let optionalString = typename.last {
106 | return optionalString == "?"
107 | }
108 | return false
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/IBAnalyzer/Parsers/UIKitOutlets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIKitOutlets.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 17/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// Special outlets declared in UIKit classes.
12 | private let uiKitOutlets: [String: [String]] = [
13 | "UITextField": ["delegate"],
14 | "UITableView": ["delegate", "dataSource"],
15 | "UITableViewCell": ["accessoryView", "backgroundView", "editingAccessoryView", "selectedBackgroundView"],
16 | "UICollectionView": ["delegate", "dataSource", "prefetchDataSource"],
17 | "UICollectionViewCell": ["backgroundView", "selectedBackgroundView"],
18 | "UITextView": ["delegate"],
19 | "UIScrollView": ["delegate"],
20 | "UIPickerView": ["delegate", "dataSource"],
21 | "MKMapView": ["delegate"],
22 | "GLKView": ["delegate"],
23 | "SCNView": ["delegate"],
24 | "UIWebView": ["delegate"],
25 | "UITapGestureRecognizer": ["delegate"],
26 | "UIPinchGestureRecognizer": ["delegate"],
27 | "UIRotationGestureRecognizer": ["delegate"],
28 | "UISwipeGestureRecognizer": ["delegate"],
29 | "UIPanGestureRecognizer": ["delegate"],
30 | "UIScreenEdgePanGestureRecognizer": ["delegate"],
31 | "UILongPressGestureRecognizer": ["delegate"],
32 | "UIGestureRecognizer": ["delegate"],
33 | "UINavigationBar": ["delegate"],
34 | "UINavigationItem": ["backBarButtonItem", "leftBarButtonItem", "rightBarButtonItem", "titleView"],
35 | "UIToolbar": ["delegate"],
36 | "UITabBar": ["delegate"],
37 | "UISearchBar": ["delegate"],
38 | "UIViewController": ["view"]
39 | ]
40 |
41 | func uiKitClassNameToClass() -> [String: Class] {
42 | var dict: [String: Class] = [:]
43 | for (name, outlets) in uiKitOutlets {
44 | var outletArray: [Declaration] = []
45 | for outlet in outlets {
46 | outletArray.append(Declaration(name: outlet, line: 0, column: 0))
47 | }
48 | dict[name] = Class(outlets: outletArray, actions: [], inherited: [])
49 | }
50 |
51 | return dict
52 | }
53 |
--------------------------------------------------------------------------------
/IBAnalyzer/Runner.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Runner.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 29/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SourceKittenFramework
11 |
12 | class Runner {
13 | let path: String
14 | let directoryEnumerator: DirectoryContentsEnumeratorType
15 | let nibParser: NibParserType
16 | let swiftParser: SwiftParserType
17 | let fileManager: FileManager
18 |
19 | init(path: String,
20 | directoryEnumerator: DirectoryContentsEnumeratorType = DirectoryContentsEnumerator(),
21 | nibParser: NibParserType = NibParser(),
22 | swiftParser: SwiftParserType = SwiftParser(),
23 | fileManager: FileManager = FileManager()) {
24 | self.path = path
25 | self.directoryEnumerator = directoryEnumerator
26 | self.nibParser = nibParser
27 | self.swiftParser = swiftParser
28 | self.fileManager = fileManager
29 | }
30 |
31 | func issues(using analyzers: [Analyzer]) throws -> [Issue] {
32 | var classNameToNibMap: [String: Nib] = [:]
33 | var classNameToClassMap: [String: Class] = [:]
34 |
35 | for url in try nibFiles() {
36 | let connections = try nibParser.mappingForFile(at: url)
37 | for (key, value) in connections {
38 | classNameToNibMap[key] = value
39 | }
40 | }
41 |
42 | for url in try swiftFiles() {
43 | try swiftParser.mappingForFile(at: url, result: &classNameToClassMap)
44 | }
45 |
46 | let configuration = AnalyzerConfiguration(classNameToNibMap: classNameToNibMap,
47 | classNameToClassMap: classNameToClassMap,
48 | uiKitClassNameToClassMap: uiKitClassNameToClass())
49 |
50 | return analyzers.flatMap { $0.issues(for: configuration) }
51 | }
52 |
53 | func nibFiles() throws -> [URL] {
54 | return try files().filter { $0.pathExtension == "storyboard" || $0.pathExtension == "xib"}
55 | }
56 |
57 | func swiftFiles() throws -> [URL] {
58 | return try files().filter { $0.pathExtension == "swift" }
59 | }
60 |
61 | fileprivate func files() throws -> [URL] {
62 | let url = URL(fileURLWithPath: path)
63 | return try directoryEnumerator.files(at: url, fileManager: fileManager)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/IBAnalyzer/main.swift:
--------------------------------------------------------------------------------
1 | //
2 | // main.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 24-12-16.
6 | // Copyright © 2016 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import AppKit
11 |
12 | let isInUnitTests = NSClassFromString("XCTest") != nil
13 |
14 | if !isInUnitTests {
15 | do {
16 | let args = ProcessInfo.processInfo.arguments
17 | guard args.count > 1 else {
18 | print("Please provide a project path as a first argument.")
19 | exit(1)
20 | }
21 |
22 | let currentDirectoryPath = FileManager.default.currentDirectoryPath
23 | let url = URL(fileURLWithPath: args[1], relativeTo: URL(fileURLWithPath: currentDirectoryPath))
24 |
25 | guard FileManager.default.fileExists(atPath: url.path) else {
26 | print("Path \(url.path) doesn't exist.")
27 | exit(1)
28 | }
29 |
30 | print("Analyzing files located at: \(url.path)")
31 |
32 | let runner = Runner(path: url.path)
33 | Configuration.shared.setup(with: args)
34 | let issues = try runner.issues(using: [ConnectionAnalyzer()])
35 | var hasSeriousViolation: Bool = false
36 | for issue in issues {
37 | if issue.isSeriousViolation {
38 | hasSeriousViolation = true
39 | }
40 | print(issue)
41 | }
42 | if hasSeriousViolation {
43 | exit(2)
44 | }
45 | } catch let error {
46 | print(error.localizedDescription)
47 | exit(1)
48 | }
49 | } else {
50 | final class TestAppDelegate: NSObject, NSApplicationDelegate {
51 | let window = NSWindow()
52 |
53 | func applicationDidFinishLaunching(aNotification: NSNotification) {
54 | window.setFrame(CGRect(x: 0, y: 0, width: 0, height: 0), display: false)
55 | window.makeKeyAndOrderFront(self)
56 | }
57 | }
58 |
59 | // This is required for us to be able to run unit tests.
60 | autoreleasepool { () -> Void in
61 | let app = NSApplication.shared()
62 | let appDelegate = TestAppDelegate()
63 | app.delegate = appDelegate
64 | app.run()
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/ConnectionAnalyzerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConnectionAnalyzerTests.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 14/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import IBAnalyzer
11 |
12 | extension ConnectionIssue: Equatable {
13 | public static func == (lhs: ConnectionIssue, rhs: ConnectionIssue) -> Bool {
14 | // Not pretty but probably good enough for tests.
15 | return String(describing: lhs) == String(describing: rhs)
16 | }
17 | }
18 |
19 | class ConnectionAnalyzerTests: XCTestCase {
20 | func testNoOutletsAndActions() {
21 | let nib = Nib(outlets: [], actions: [])
22 | let klass = Class(outlets: [], actions: [], inherited: [])
23 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["A": nib],
24 | classNameToClassMap: ["A": klass])
25 | XCTAssertEqual(issues(for: configuration), [])
26 | }
27 |
28 | func testMissingOutlet() {
29 | let label = Declaration(name: "label", line: 1, column: 0)
30 | let nib = Nib(outlets: [label], actions: [])
31 | let klass = Class(outlets: [], actions: [], inherited: [])
32 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["A": nib],
33 | classNameToClassMap: ["A": klass])
34 | XCTAssertEqual(issues(for: configuration), [ConnectionIssue.missingOutlet(className: "A", outlet: label)])
35 | }
36 |
37 | func testMissingAction() {
38 | let didTapButton = Declaration(name: "didTapButton:", line: 1, column: 0)
39 | let nib = Nib(outlets: [], actions: [didTapButton])
40 | let klass = Class(outlets: [], actions: [], inherited: [])
41 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["A": nib],
42 | classNameToClassMap: ["A": klass])
43 | XCTAssertEqual(issues(for: configuration),
44 | [ConnectionIssue.missingAction(className: "A", action: didTapButton)])
45 | }
46 |
47 | func testUnnecessaryOutlet() {
48 | let nib = Nib(outlets: [], actions: [])
49 | let label = Declaration(name: "label", line: 1, column: 0)
50 | let klass = Class(outlets: [label], actions: [], inherited: [])
51 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["A": nib],
52 | classNameToClassMap: ["A": klass])
53 | XCTAssertEqual(issues(for: configuration),
54 | [ConnectionIssue.unnecessaryOutlet(className: "A", outlet: label)])
55 | }
56 |
57 | func testUnnecessaryAction() {
58 | let nib = Nib(outlets: [], actions: [])
59 | let didTapButton = Declaration(name: "didTapButton:", line: 1, column: 0)
60 | let klass = Class(outlets: [], actions: [didTapButton], inherited: [])
61 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["A": nib],
62 | classNameToClassMap: ["A": klass])
63 | XCTAssertEqual(issues(for: configuration),
64 | [ConnectionIssue.unnecessaryAction(className: "A", action: didTapButton)])
65 | }
66 |
67 | func testNoIssueWhenOutletInSuperClass() {
68 | let label = Declaration(name: "label", line: 1, column: 0)
69 | let nib = Nib(outlets: [label], actions: [])
70 | let map = ["A": Class(outlets: [label], actions: [], inherited: []),
71 | "B": Class(outlets: [], actions: [], inherited: ["A"])]
72 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["B": nib],
73 | classNameToClassMap: map)
74 | XCTAssertEqual(issues(for: configuration), [])
75 | }
76 |
77 | func testNoIssueWhenOutletInSuperSuperClass() {
78 | let label = Declaration(name: "label", line: 1, column: 0)
79 | let nib = Nib(outlets: [label], actions: [])
80 | let map = ["A": Class(outlets: [label], actions: [], inherited: []),
81 | "B": Class(outlets: [], actions: [], inherited: ["A"]),
82 | "C": Class(outlets: [], actions: [], inherited: ["B"])]
83 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["C": nib],
84 | classNameToClassMap: map)
85 | XCTAssertEqual(issues(for: configuration), [])
86 | }
87 |
88 | func testNoIssueWhenActionInSuperClass() {
89 | let didTapButton = Declaration(name: "didTapButton:", line: 1, column: 0)
90 | let nib = Nib(outlets: [], actions: [didTapButton])
91 | let map = ["A": Class(outlets: [], actions: [didTapButton], inherited: []),
92 | "B": Class(outlets: [], actions: [], inherited: ["A"]),
93 | "C": Class(outlets: [], actions: [], inherited: ["B"])]
94 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["C": nib],
95 | classNameToClassMap: map)
96 | XCTAssertEqual(issues(for: configuration), [])
97 | }
98 |
99 | func testUsesUIKitClasses() {
100 | let delegate = Declaration(name: "delegate:", line: 1, column: 0)
101 | let nib = Nib(outlets: [delegate], actions: [])
102 | let klass = Class(outlets: [], actions: [], inherited: ["UITextField"])
103 | let textField = Class(outlets: [delegate], actions: [], inherited: [])
104 | let configuration = AnalyzerConfiguration(classNameToNibMap: ["A": nib],
105 | classNameToClassMap: ["A": klass],
106 | uiKitClassNameToClassMap: ["UITextField": textField])
107 | XCTAssertEqual(issues(for: configuration), [])
108 | }
109 |
110 | private func issues(for configuration: AnalyzerConfiguration) -> [ConnectionIssue] {
111 | let analyzer = ConnectionAnalyzer()
112 | return (analyzer.issues(for: configuration) as? [ConnectionIssue]) ?? []
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/DirectoryContentsEnumeratorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DirectoryContentsEnumeratorTests.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 14/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import IBAnalyzer
11 |
12 | // swiftlint:disable force_try
13 | // swiftlint:disable line_length
14 | class DirectoryContentsEnumeratorTests: XCTestCase {
15 |
16 | var directoryEnumerator = DirectoryContentsEnumerator()
17 |
18 | func testFlatDirectory() {
19 | let directoryURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString, isDirectory: true)!
20 | try! FileManager.default.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
21 | let fileURL = directoryURL.appendingPathComponent("file.txt")
22 | try! "test".data(using: .utf8)?.write(to: fileURL)
23 |
24 | let files = try! directoryEnumerator.files(at: directoryURL)
25 | XCTAssertEqual(files, [fileURL])
26 | }
27 |
28 | func testNestedDirectory() {
29 | let directoryURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString, isDirectory: true)!
30 | try! FileManager.default.createDirectory(at: directoryURL,
31 | withIntermediateDirectories: true,
32 | attributes: nil)
33 | let fileURL = directoryURL.appendingPathComponent("file.txt")
34 | try! "test".data(using: .utf8)?.write(to: fileURL)
35 |
36 | let subDirectoryURL = directoryURL.appendingPathComponent("sub", isDirectory: true)
37 | try! FileManager.default.createDirectory(at: subDirectoryURL,
38 | withIntermediateDirectories: true,
39 | attributes: nil)
40 |
41 | let fileInSubURL = subDirectoryURL.appendingPathComponent("file2.txt")
42 | try! "test2".data(using: .utf8)?.write(to: fileInSubURL)
43 |
44 | let files = try! directoryEnumerator.files(at: directoryURL)
45 | XCTAssertEqual(files, [fileURL, fileInSubURL])
46 | }
47 |
48 | func testEmptyForNonExistingDirectory() {
49 | let files = try! directoryEnumerator.files(at: URL(fileURLWithPath: "/incorrect/"))
50 | XCTAssertEqual(files, [])
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/Examples/Example.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/NibParserTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NibParserTests.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 27-12-16.
6 | // Copyright © 2016 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import IBAnalyzer
11 |
12 | class NibParserTests: XCTestCase {
13 |
14 | func testExampleStoryboard() {
15 | guard let srcRoot = ProcessInfo.processInfo.environment["SRCROOT"] else {
16 | fatalError("SRCROOT should be non-nil")
17 | }
18 |
19 | let path = "/IBAnalyzerTests/Examples/Example.storyboard"
20 | let storyboardPath = (srcRoot as NSString).appendingPathComponent(path)
21 | let url = URL(fileURLWithPath: storyboardPath)
22 | let parser = NibParser()
23 | let button = Declaration(name: "button", line: 1, column: 0)
24 | let titleLabel = Declaration(name: "titleLabel", line: 1, column: 0)
25 | let didTapButton = Declaration(name: "didTapButton:", line: 1, column: 0)
26 | let expected = ["ViewController": Nib(outlets: [button, titleLabel], actions: [didTapButton]),
27 | "ViewController2": Nib(outlets: [], actions: [])]
28 | do {
29 | let result = try parser.mappingForFile(at: url)
30 | XCTAssertEqual(result, expected)
31 | } catch let error {
32 | XCTFail(error.localizedDescription)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RunnerTests.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 29/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | import SourceKittenFramework
11 | @testable import IBAnalyzer
12 |
13 | private class MockAnalyzer: Analyzer {
14 | var lastUsedConfiguration: AnalyzerConfiguration?
15 |
16 | func issues(for configuration: AnalyzerConfiguration) -> [Issue] {
17 | lastUsedConfiguration = configuration
18 | return []
19 | }
20 | }
21 |
22 | class RunnerTests: XCTestCase {
23 | func testCallsAnalyzerWithCorrectConfiguration() {
24 | let runner = Runner(path: "example",
25 | directoryEnumerator: StubFineDirectoryContentsEnumerator(),
26 | nibParser: StubNibParser(),
27 | swiftParser: StubSwiftParser(),
28 | fileManager: FileManager.default)
29 |
30 | let mockAnalyzer = MockAnalyzer()
31 | do {
32 | _ = try runner.issues(using: [mockAnalyzer])
33 | let configuration = mockAnalyzer.lastUsedConfiguration!
34 |
35 | let nibMap = StubNibParser.cMap.merging(other: StubNibParser.dMap)
36 | XCTAssertEqual(configuration.classNameToNibMap, nibMap)
37 |
38 | let swiftMap = StubSwiftParser.aMap.merging(other: StubSwiftParser.eMap)
39 | XCTAssertEqual(configuration.classNameToClassMap, swiftMap)
40 | } catch let error {
41 | XCTFail("Unexpected error: \(error)")
42 | }
43 | }
44 | }
45 |
46 | class RunnerFilesTests: XCTestCase {
47 |
48 | func testNibFiles() {
49 | let runner = Runner(path: "example", directoryEnumerator: StubFineDirectoryContentsEnumerator())
50 | XCTAssertEqual(try runner.nibFiles(), ["c.xib", "d.storyboard"].map { URL(fileURLWithPath: $0) })
51 | }
52 |
53 | func testSwiftFiles() {
54 | let runner = Runner(path: "example", directoryEnumerator: StubFineDirectoryContentsEnumerator())
55 | XCTAssertEqual(try runner.swiftFiles(), ["a.swift", "e.swift"].map { URL(fileURLWithPath: $0) })
56 | }
57 |
58 | func testNibFilesThrows() {
59 | let runner = Runner(path: "example", directoryEnumerator: StubThrowingDirectoryContentsEnumerator())
60 | XCTAssertThrowsError(try runner.nibFiles())
61 | }
62 |
63 | func testSwiftFilesThrows() {
64 | let runner = Runner(path: "example", directoryEnumerator: StubThrowingDirectoryContentsEnumerator())
65 | XCTAssertThrowsError(try runner.swiftFiles())
66 | }
67 | }
68 |
69 | private extension Dictionary {
70 | func merging(other: [Key: Value]) -> [Key: Value] {
71 | var mutableCopy = self
72 | for (key, value) in other {
73 | // If both dictionaries have a value for same key, the value of the other dictionary is used.
74 | mutableCopy[key] = value
75 | }
76 | return mutableCopy
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/Stubs.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Stubs.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 29/01/2017.
6 | // Copyright © 2017 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | @testable import IBAnalyzer
11 |
12 | struct StubFineDirectoryContentsEnumerator: DirectoryContentsEnumeratorType {
13 | func files(at url: URL, fileManager: FileManager) throws -> [URL] {
14 | return ["a.swift", "b.m", "c.xib", "d.storyboard", "e.swift", "f.swift2"].map {
15 | URL(fileURLWithPath: $0)
16 | }
17 | }
18 | }
19 |
20 | struct StubThrowingDirectoryContentsEnumerator: DirectoryContentsEnumeratorType {
21 | func files(at url: URL, fileManager: FileManager) throws -> [URL] {
22 | throw NSError(domain: "test", code: 0, userInfo: nil)
23 | }
24 | }
25 |
26 | struct StubNibParser: NibParserType {
27 | static let button = Declaration(name: "button", line: 1, column: 0)
28 | static let label = Declaration(name: "label", line: 1, column: 0)
29 | static let cMap = ["C": Nib(outlets: [StubNibParser.label, StubNibParser.button], actions: [])]
30 | static let tappedButton = Declaration(name: "tappedButton:", line: 1, column: 0)
31 | static let titleView = Declaration(name: "titleView", line: 1, column: 0)
32 | static let dMap = ["FirstViewController": Nib(outlets: [], actions: [StubNibParser.tappedButton]),
33 | "SecondViewController": Nib(outlets: [StubNibParser.titleView], actions: [])]
34 |
35 | func mappingForFile(at url: URL) throws -> [String: Nib] {
36 | switch url {
37 | case URL(fileURLWithPath: "c.xib"):
38 | return type(of: self).cMap
39 | case URL(fileURLWithPath: "d.storyboard"):
40 | return type(of: self).dMap
41 | default:
42 | fatalError()
43 | }
44 | }
45 | }
46 |
47 | struct StubSwiftParser: SwiftParserType {
48 | static let label = Declaration(name: "label", line: 1, column: 0)
49 | static let aMap = ["C": Class(outlets: [StubSwiftParser.label], actions: [], inherited: [])]
50 | static let buttonTapped = Declaration(name: "buttonTapped:", line: 1, column: 0)
51 | static let eMap = ["FirstViewController": Class(outlets: [], actions: [StubSwiftParser.buttonTapped], inherited: [])]
52 |
53 | func mappingForFile(at url: URL, result: inout [String: Class]) throws {
54 | switch url {
55 | case URL(fileURLWithPath: "a.swift"):
56 | result += type(of: self).aMap
57 | case URL(fileURLWithPath: "e.swift"):
58 | result += type(of: self).eMap
59 | default:
60 | fatalError()
61 | }
62 | }
63 |
64 | func mappingForContents(_ contents: String, result: inout [String: Class]) throws {
65 | //do nothing
66 | }
67 | }
68 |
69 | func += (left: inout [K: V], right: [K: V]) {
70 | for (key, value) in right {
71 | left.updateValue(value, forKey: key)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/IBAnalyzerTests/SwiftParserTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftParserTests.swift
3 | // IBAnalyzer
4 | //
5 | // Created by Arkadiusz Holko on 26-12-16.
6 | // Copyright © 2016 Arkadiusz Holko. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | import SourceKittenFramework
11 | @testable import IBAnalyzer
12 |
13 | // swiftlint:disable line_length
14 | class SwiftParserTests: XCTestCase {
15 |
16 | func testViewControllerWithoutOutletsAndActions() {
17 | let source = "class TestViewController: UIViewController { var button: UIButton!; func didTapButton(_ sender: UIButton) {} }"
18 |
19 | let expected = Class(outlets: [], actions: [], inherited: ["UIViewController"])
20 | XCTAssertEqual(mappingFor(contents: source), ["TestViewController": expected])
21 | }
22 |
23 | func testViewControllerWithOneOutlet() {
24 | let source = "class TestViewController: UIViewController { @IBOutlet weak var button: UIButton! }"
25 | let button = Declaration(name: "button", line: 1, column: 0)
26 | let expected = Class(outlets: [button], actions: [], inherited: ["UIViewController"])
27 | XCTAssertEqual(mappingFor(contents: source), ["TestViewController": expected])
28 | }
29 |
30 | func testNestedViewControllerWithOneOutlet() {
31 | let source = "class Outer { class TestViewController: UIViewController { @IBOutlet weak var button: UIButton! }}"
32 |
33 | let expectedOuter = Class(outlets: [], actions: [], inherited: [])
34 | let button = Declaration(name: "button", line: 1, column: 0)
35 | let expectedInner = Class(outlets: [button], actions: [], inherited: ["UIViewController"])
36 | XCTAssertEqual(mappingFor(contents: source), ["Outer": expectedOuter,
37 | "TestViewController": expectedInner])
38 | }
39 |
40 | func testViewControllerWithOneAction() {
41 | let source = "class TestViewController: UIViewController { @IBAction func didTapButton(_ sender: UIButton) {} }"
42 |
43 | let didTapButton = Declaration(name: "didTapButton:", line: 1, column: 0)
44 | let expected = Class(outlets: [], actions: [didTapButton], inherited: ["UIViewController"])
45 | XCTAssertEqual(mappingFor(contents: source), ["TestViewController": expected])
46 | }
47 |
48 | func testMultipleInheritance() {
49 | let source = "class TestViewController: UIViewController, SomeProtocol { }"
50 |
51 | let expected = Class(outlets: [], actions: [], inherited: ["UIViewController", "SomeProtocol"])
52 | XCTAssertEqual(mappingFor(contents: source), ["TestViewController": expected])
53 | }
54 |
55 | func testViewControllerWithActionInExtension() {
56 | let source = "class TestViewController: UIViewController {}; extension TestViewController { @IBAction func didTapButton(_ sender: UIButton) {} }"
57 |
58 | let didTapButton = Declaration(name: "didTapButton:", line: 1, column: 0)
59 | let expected = Class(outlets: [], actions: [didTapButton], inherited: ["UIViewController"])
60 | XCTAssertEqual(mappingFor(contents: source), ["TestViewController": expected])
61 | }
62 |
63 | private func mappingFor(contents: String) -> [String: Class] {
64 | let parser = SwiftParser()
65 | var result: [String: Class] = [:]
66 | do {
67 | try parser.mappingForContents(contents, result: &result)
68 | } catch let error {
69 | XCTFail(error.localizedDescription)
70 | }
71 | return result
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Arkadiusz Holko
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 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | # platform :osx, '10.12'
3 |
4 | target 'IBAnalyzer' do
5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | pod 'SourceKittenFramework', '~> 0.19'
9 | pod 'SwiftLint', '~> 0.25.1'
10 | target 'IBAnalyzerTests' do
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - SourceKittenFramework (0.19.1):
3 | - SWXMLHash (~> 4.1)
4 | - Yams (~> 0.5.0)
5 | - SwiftLint (0.25.1)
6 | - SWXMLHash (4.5.0)
7 | - Yams (0.5.0)
8 |
9 | DEPENDENCIES:
10 | - SourceKittenFramework (~> 0.19)
11 | - SwiftLint (~> 0.25.1)
12 |
13 | SPEC REPOS:
14 | https://github.com/cocoapods/specs.git:
15 | - SourceKittenFramework
16 | - SwiftLint
17 | - SWXMLHash
18 | - Yams
19 |
20 | SPEC CHECKSUMS:
21 | SourceKittenFramework: ef76be16e76ffa0a64b00c5eb053e87c6770dcdb
22 | SwiftLint: ce933681be10c3266e82576dad676fa815a602e9
23 | SWXMLHash: 5d980b1f12ff0ee2bd9a26df1e01377dc91dfb6e
24 | Yams: 58b13424ca380835c4c797bc775ce6cbb3bc0167
25 |
26 | PODFILE CHECKSUM: e9eb876508bb57d7b03a4c6a6146c2eb1e0051a2
27 |
28 | COCOAPODS: 1.5.3
29 |
--------------------------------------------------------------------------------
/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - SourceKittenFramework (0.19.1):
3 | - SWXMLHash (~> 4.1)
4 | - Yams (~> 0.5.0)
5 | - SwiftLint (0.25.1)
6 | - SWXMLHash (4.5.0)
7 | - Yams (0.5.0)
8 |
9 | DEPENDENCIES:
10 | - SourceKittenFramework (~> 0.19)
11 | - SwiftLint (~> 0.25.1)
12 |
13 | SPEC REPOS:
14 | https://github.com/cocoapods/specs.git:
15 | - SourceKittenFramework
16 | - SwiftLint
17 | - SWXMLHash
18 | - Yams
19 |
20 | SPEC CHECKSUMS:
21 | SourceKittenFramework: ef76be16e76ffa0a64b00c5eb053e87c6770dcdb
22 | SwiftLint: ce933681be10c3266e82576dad676fa815a602e9
23 | SWXMLHash: 5d980b1f12ff0ee2bd9a26df1e01377dc91dfb6e
24 | Yams: 58b13424ca380835c4c797bc775ce6cbb3bc0167
25 |
26 | PODFILE CHECKSUM: e9eb876508bb57d7b03a4c6a6146c2eb1e0051a2
27 |
28 | COCOAPODS: 1.5.3
29 |
--------------------------------------------------------------------------------
/Pods/Manifest.lock-e:
--------------------------------------------------------------------------------
1 | PODS:
2 | - SourceKittenFramework (0.16.0):
3 | - SWXMLHash (~> 3.0)
4 | - Yams (~> 0.1)
5 | - SwiftLint (0.16.0)
6 | - SWXMLHash (3.0.3)
7 | - Yams (0.1.4)
8 |
9 | DEPENDENCIES:
10 | - SourceKittenFramework (~> 0.16.0)
11 | - SwiftLint (~> 0.16.0)
12 |
13 | SPEC CHECKSUMS:
14 | SourceKittenFramework: 84afd2293a7278ee99a0a1d7dea29f36c9ef3cda
15 | SwiftLint: 90665265ae50b58167c674a11c680bbabe9d6513
16 | SWXMLHash: 80d2529d74891bb2f15305a0b9e08f2a4f229ee7
17 | Yams: 4a4d2b5f0db216fab03c6abc04b7692ceff7cf5f
18 |
19 | PODFILE CHECKSUM: 18620891bf2d6386f04a3125a4e9b431d601c978
20 |
21 | COCOAPODS: 1.1.1
22 |
--------------------------------------------------------------------------------
/Pods/SWXMLHash/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 David Mohundro
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 JP Simard.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/ClangTranslationUnit.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClangTranslationUnit.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-12.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | #if !os(Linux)
10 |
11 | #if SWIFT_PACKAGE
12 | import Clang_C
13 | #endif
14 | import Foundation
15 |
16 | extension Sequence where Iterator.Element: Hashable {
17 | fileprivate func distinct() -> [Iterator.Element] {
18 | return Array(Set(self))
19 | }
20 | }
21 |
22 | extension Sequence {
23 | fileprivate func grouped(by transform: (Iterator.Element) -> U) -> [U: [Iterator.Element]] {
24 | return reduce([:]) { dictionary, element in
25 | var dictionary = dictionary
26 | let key = transform(element)
27 | dictionary[key] = (dictionary[key] ?? []) + [element]
28 | return dictionary
29 | }
30 | }
31 | }
32 |
33 | extension Dictionary {
34 | fileprivate init(_ pairs: [Element]) {
35 | self.init()
36 | for (k, v) in pairs {
37 | self[k] = v
38 | }
39 | }
40 |
41 | fileprivate func map(transform: (Value) throws -> (OutValue)) rethrows -> [Key: OutValue] {
42 | return [Key: OutValue](try map { ($0.key, try transform($0.value)) })
43 | }
44 | }
45 |
46 | /// Represents a group of CXTranslationUnits.
47 | public struct ClangTranslationUnit {
48 | /// Array of CXTranslationUnits.
49 | private let clangTranslationUnits: [CXTranslationUnit]
50 |
51 | public let declarations: [String: [SourceDeclaration]]
52 |
53 | /**
54 | Create a ClangTranslationUnit by passing Objective-C header files and clang compiler arguments.
55 |
56 | - parameter headerFiles: Objective-C header files to document.
57 | - parameter compilerArguments: Clang compiler arguments.
58 | */
59 | public init(headerFiles: [String], compilerArguments: [String]) {
60 | let cStringCompilerArguments = compilerArguments.map { ($0 as NSString).utf8String }
61 | let clangIndex = ClangIndex()
62 | clangTranslationUnits = headerFiles.map { clangIndex.open(file: $0, args: cStringCompilerArguments) }
63 | declarations = clangTranslationUnits
64 | .flatMap { $0.cursor().flatMap({ SourceDeclaration(cursor: $0, compilerArguments: compilerArguments) }) }
65 | .rejectEmptyDuplicateEnums()
66 | .distinct()
67 | .sorted()
68 | .grouped { $0.location.file }
69 | .map { insertMarks(declarations: $0) }
70 | }
71 |
72 | /**
73 | Failable initializer to create a ClangTranslationUnit by passing Objective-C header files and
74 | `xcodebuild` arguments. Optionally pass in a `path`.
75 |
76 | - parameter headerFiles: Objective-C header files to document.
77 | - parameter xcodeBuildArguments: The arguments necessary pass in to `xcodebuild` to link these header files.
78 | - parameter path: Path to run `xcodebuild` from. Uses current path by default.
79 | */
80 | public init?(headerFiles: [String], xcodeBuildArguments: [String], inPath path: String = FileManager.default.currentDirectoryPath) {
81 | let xcodeBuildOutput = runXcodeBuild(arguments: xcodeBuildArguments + ["-dry-run"], inPath: path) ?? ""
82 | guard let clangArguments = parseCompilerArguments(xcodebuildOutput: xcodeBuildOutput as NSString, language: .objc, moduleName: nil) else {
83 | fputs("could not parse compiler arguments\n\(xcodeBuildOutput)\n", stderr)
84 | return nil
85 | }
86 | self.init(headerFiles: headerFiles, compilerArguments: clangArguments)
87 | }
88 | }
89 |
90 | // MARK: CustomStringConvertible
91 |
92 | extension ClangTranslationUnit: CustomStringConvertible {
93 | /// A textual JSON representation of `ClangTranslationUnit`.
94 | public var description: String {
95 | return declarationsToJSON(declarations) + "\n"
96 | }
97 | }
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/CodeCompletionItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CodeCompletionItem.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 9/4/15.
6 | // Copyright © 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | fileprivate extension Dictionary {
12 | mutating func addIfNotNil(_ key: Key, _ value: Value?) {
13 | if let value = value {
14 | self[key] = value
15 | }
16 | }
17 | }
18 |
19 | public struct CodeCompletionItem: CustomStringConvertible {
20 | #if os(Linux)
21 | public typealias NumBytesInt = Int
22 | #else
23 | public typealias NumBytesInt = Int64
24 | #endif
25 |
26 | public let kind: String
27 | public let context: String
28 | public let name: String?
29 | public let descriptionKey: String?
30 | public let sourcetext: String?
31 | public let typeName: String?
32 | public let moduleName: String?
33 | public let docBrief: String?
34 | public let associatedUSRs: String?
35 | public let numBytesToErase: NumBytesInt?
36 |
37 | /// Dictionary representation of CodeCompletionItem. Useful for NSJSONSerialization.
38 | public var dictionaryValue: [String: Any] {
39 | var dict: [String: Any] = ["kind": kind, "context": context]
40 | dict.addIfNotNil("name", name)
41 | dict.addIfNotNil("descriptionKey", descriptionKey)
42 | dict.addIfNotNil("sourcetext", sourcetext)
43 | dict.addIfNotNil("typeName", typeName)
44 | dict.addIfNotNil("moduleName", moduleName)
45 | dict.addIfNotNil("docBrief", docBrief)
46 | dict.addIfNotNil("associatedUSRs", associatedUSRs)
47 | dict.addIfNotNil("numBytesToErase", numBytesToErase)
48 | return dict
49 | }
50 |
51 | public var description: String {
52 | return toJSON(dictionaryValue.bridge())
53 | }
54 |
55 | public static func parse(response: [String: SourceKitRepresentable]) -> [CodeCompletionItem] {
56 | return (response["key.results"] as! [SourceKitRepresentable]).map { item in
57 | let dict = item as! [String: SourceKitRepresentable]
58 | return CodeCompletionItem(kind: dict["key.kind"] as! String,
59 | context: dict["key.context"] as! String,
60 | name: dict["key.name"] as? String,
61 | descriptionKey: dict["key.description"] as? String,
62 | sourcetext: dict["key.sourcetext"] as? String,
63 | typeName: dict["key.typename"] as? String,
64 | moduleName: dict["key.modulename"] as? String,
65 | docBrief: dict["key.doc.brief"] as? String,
66 | associatedUSRs: dict["key.associated_usrs"] as? String,
67 | numBytesToErase: dict["key.num_bytes_to_erase"] as? NumBytesInt)
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Dictionary+Merge.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Dictionary+Merge.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-08.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | /**
10 | Returns a new dictionary by adding the entries of dict2 into dict1, overriding if the key exists.
11 |
12 | - parameter dict1: Dictionary to merge into.
13 | - parameter dict2: Dictionary to merge from (optional).
14 |
15 | - returns: A new dictionary by adding the entries of dict2 into dict1, overriding if the key exists.
16 | */
17 | internal func merge(_ dict1: [K: V], _ dict2: [K: V]?) -> [K: V] {
18 | var mergedDict = dict1
19 | if let dict2 = dict2 {
20 | for (key, value) in dict2 {
21 | mergedDict[key] = value
22 | }
23 | }
24 | return mergedDict
25 | }
26 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Documentation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Documentation.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 10/27/15.
6 | // Copyright © 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | #if !os(Linux)
10 |
11 | #if SWIFT_PACKAGE
12 | import Clang_C
13 | #endif
14 |
15 | public struct Documentation {
16 | public let parameters: [Parameter]
17 | public let returnDiscussion: [Text]
18 |
19 | init(comment: CXComment) {
20 | let comments = (0.. String {
19 | if let array = object as? [Any], array.isEmpty {
20 | return "[\n\n]"
21 | }
22 | do {
23 | let options: JSONSerialization.WritingOptions
24 | #if os(Linux)
25 | options = [.prettyPrinted, .sortedKeys]
26 | #else
27 | if #available(macOS 10.13, *) {
28 | options = [.prettyPrinted, .sortedKeys]
29 | } else {
30 | options = .prettyPrinted
31 | }
32 | #endif
33 | let prettyJSONData = try JSONSerialization.data(withJSONObject: object, options: options)
34 | if let jsonString = String(data: prettyJSONData, encoding: .utf8) {
35 | return jsonString
36 | }
37 | } catch {}
38 | return ""
39 | }
40 |
41 | /**
42 | Convert [String: SourceKitRepresentable] to `NSDictionary`.
43 |
44 | - parameter dictionary: [String: SourceKitRepresentable] to convert.
45 |
46 | - returns: JSON-serializable value.
47 | */
48 | public func toNSDictionary(_ dictionary: [String: SourceKitRepresentable]) -> NSDictionary {
49 | var anyDictionary = [String: Any]()
50 | for (key, object) in dictionary {
51 | switch object {
52 | case let object as [SourceKitRepresentable]:
53 | anyDictionary[key] = object.map { toNSDictionary($0 as! [String: SourceKitRepresentable]) }
54 | case let object as [[String: SourceKitRepresentable]]:
55 | anyDictionary[key] = object.map { toNSDictionary($0) }
56 | case let object as [String: SourceKitRepresentable]:
57 | anyDictionary[key] = toNSDictionary(object)
58 | case let object as String:
59 | anyDictionary[key] = object
60 | case let object as Int64:
61 | anyDictionary[key] = NSNumber(value: object)
62 | case let object as Bool:
63 | anyDictionary[key] = NSNumber(value: object)
64 | case let object as Any:
65 | anyDictionary[key] = object
66 | default:
67 | fatalError("Should never happen because we've checked all SourceKitRepresentable types")
68 | }
69 | }
70 | return anyDictionary.bridge()
71 | }
72 |
73 | #if !os(Linux)
74 |
75 | public func declarationsToJSON(_ decl: [String: [SourceDeclaration]]) -> String {
76 | let keyValueToDictionary: ((String, [SourceDeclaration])) -> [String: Any] = { [$0.0: toOutputDictionary($0.1)] }
77 | let dictionaries: [[String: Any]] = decl.map(keyValueToDictionary).sorted { $0.keys.first! < $1.keys.first! }
78 | return toJSON(dictionaries)
79 | }
80 |
81 | private func toOutputDictionary(_ decl: SourceDeclaration) -> [String: Any] {
82 | var dict = [String: Any]()
83 | func set(_ key: SwiftDocKey, _ value: Any?) {
84 | if let value = value {
85 | dict[key.rawValue] = value
86 | }
87 | }
88 | func setA(_ key: SwiftDocKey, _ value: [Any]?) {
89 | if let value = value, !value.isEmpty {
90 | dict[key.rawValue] = value
91 | }
92 | }
93 |
94 | set(.kind, decl.type.rawValue)
95 | set(.filePath, decl.location.file)
96 | set(.docFile, decl.location.file)
97 | set(.docLine, Int(decl.location.line))
98 | set(.docColumn, Int(decl.location.column))
99 | set(.name, decl.name)
100 | set(.usr, decl.usr)
101 | set(.parsedDeclaration, decl.declaration)
102 | set(.documentationComment, decl.commentBody)
103 | set(.parsedScopeStart, Int(decl.extent.start.line))
104 | set(.parsedScopeEnd, Int(decl.extent.end.line))
105 | set(.swiftDeclaration, decl.swiftDeclaration)
106 | set(.swiftName, decl.swiftName)
107 | set(.alwaysDeprecated, decl.availability?.alwaysDeprecated)
108 | set(.alwaysUnavailable, decl.availability?.alwaysUnavailable)
109 | set(.deprecationMessage, decl.availability?.deprecationMessage)
110 | set(.unavailableMessage, decl.availability?.unavailableMessage)
111 |
112 | setA(.docResultDiscussion, decl.documentation?.returnDiscussion.map(toOutputDictionary))
113 | setA(.docParameters, decl.documentation?.parameters.map(toOutputDictionary))
114 | setA(.substructure, decl.children.map(toOutputDictionary))
115 |
116 | if decl.commentBody != nil {
117 | set(.fullXMLDocs, "")
118 | }
119 |
120 | return dict
121 | }
122 |
123 | private func toOutputDictionary(_ decl: [SourceDeclaration]) -> [String: Any] {
124 | return ["key.substructure": decl.map(toOutputDictionary), "key.diagnostic_stage": ""]
125 | }
126 |
127 | private func toOutputDictionary(_ param: Parameter) -> [String: Any] {
128 | return ["name": param.name, "discussion": param.discussion.map(toOutputDictionary)]
129 | }
130 |
131 | private func toOutputDictionary(_ text: Text) -> [String: Any] {
132 | switch text {
133 | case .para(let str, let kind):
134 | return ["kind": kind ?? "", "Para": str]
135 | case .verbatim(let str):
136 | return ["kind": "", "Verbatim": str]
137 | }
138 | }
139 |
140 | #endif
141 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Language.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Language.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-03.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | /// Language Enum.
10 | public enum Language {
11 | /// Swift.
12 | case swift
13 | /// Objective-C.
14 | case objc
15 | }
16 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/LinuxCompatibility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LinuxCompatibility.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 8/19/16.
6 | // Copyright © 2016 SourceKitten. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | #if !os(Linux) && !swift(>=4.0)
12 | extension NSTextCheckingResult {
13 | func range(at idx: Int) -> NSRange {
14 | return rangeAt(idx)
15 | }
16 | }
17 | #endif
18 |
19 | extension Array {
20 | public func bridge() -> NSArray {
21 | #if os(Linux)
22 | return NSArray(array: self)
23 | #else
24 | return self as NSArray
25 | #endif
26 | }
27 | }
28 |
29 | extension CharacterSet {
30 | public func bridge() -> NSCharacterSet {
31 | #if os(Linux)
32 | return _bridgeToObjectiveC()
33 | #else
34 | return self as NSCharacterSet
35 | #endif
36 | }
37 | }
38 |
39 | extension Dictionary {
40 | public func bridge() -> NSDictionary {
41 | #if os(Linux)
42 | return NSDictionary(dictionary: self)
43 | #else
44 | return self as NSDictionary
45 | #endif
46 | }
47 | }
48 |
49 | extension NSString {
50 | public func bridge() -> String {
51 | #if os(Linux)
52 | return _bridgeToSwift()
53 | #else
54 | return self as String
55 | #endif
56 | }
57 | }
58 |
59 | extension String {
60 | public func bridge() -> NSString {
61 | #if os(Linux)
62 | return NSString(string: self)
63 | #else
64 | return self as NSString
65 | #endif
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Module.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Module.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-07.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Yams
11 |
12 | /// Represents source module to be documented.
13 | public struct Module {
14 | /// Module Name.
15 | public let name: String
16 | /// Compiler arguments required by SourceKit to process the source files in this Module.
17 | public let compilerArguments: [String]
18 | /// Source files to be documented in this Module.
19 | public let sourceFiles: [String]
20 |
21 | /// Documentation for this Module. Typically expensive computed property.
22 | public var docs: [SwiftDocs] {
23 | var fileIndex = 1
24 | let sourceFilesCount = sourceFiles.count
25 | return sourceFiles.flatMap {
26 | let filename = $0.bridge().lastPathComponent
27 | if let file = File(path: $0) {
28 | fputs("Parsing \(filename) (\(fileIndex)/\(sourceFilesCount))\n", stderr)
29 | fileIndex += 1
30 | return SwiftDocs(file: file, arguments: compilerArguments)
31 | }
32 | fputs("Could not parse `\(filename)`. Please open an issue at https://github.com/jpsim/SourceKitten/issues with the file contents.\n", stderr)
33 | return nil
34 | }
35 | }
36 |
37 | public init?(spmName: String) {
38 | let yamlPath = ".build/debug.yaml"
39 | guard let yaml = try? Yams.compose(yaml: String(contentsOfFile: yamlPath, encoding: .utf8)),
40 | let commands = yaml?["commands"]?.mapping?.values else {
41 | fatalError("SPM build manifest does not exist at `\(yamlPath)` or does not match expected format.")
42 | }
43 | guard let moduleCommand = commands.first(where: { $0["module-name"]?.string == spmName }) else {
44 | fputs("Could not find SPM module '\(spmName)'. Here are the modules available:\n", stderr)
45 | let availableModules = commands.flatMap({ $0["module-name"]?.string })
46 | fputs("\(availableModules.map({ " - " + $0 }).joined(separator: "\n"))\n", stderr)
47 | return nil
48 | }
49 | guard let imports = moduleCommand["import-paths"]?.array(of: String.self),
50 | let otherArguments = moduleCommand["other-args"]?.array(of: String.self),
51 | let sources = moduleCommand["sources"]?.array(of: String.self) else {
52 | fatalError("SPM build manifest does not match expected format.")
53 | }
54 | name = spmName
55 | compilerArguments = {
56 | var arguments = sources
57 | arguments.append(contentsOf: ["-module-name", spmName])
58 | arguments.append(contentsOf: otherArguments)
59 | arguments.append(contentsOf: ["-I"])
60 | arguments.append(contentsOf: imports)
61 | return arguments
62 | }()
63 | sourceFiles = sources
64 | }
65 |
66 | /**
67 | Failable initializer to create a Module by the arguments necessary pass in to `xcodebuild` to build it.
68 | Optionally pass in a `moduleName` and `path`.
69 |
70 | - parameter xcodeBuildArguments: The arguments necessary pass in to `xcodebuild` to build this Module.
71 | - parameter name: Module name. Will be parsed from `xcodebuild` output if nil.
72 | - parameter path: Path to run `xcodebuild` from. Uses current path by default.
73 | */
74 | public init?(xcodeBuildArguments: [String], name: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath) {
75 | let xcodeBuildOutput = runXcodeBuild(arguments: xcodeBuildArguments, inPath: path) ?? ""
76 | guard let arguments = parseCompilerArguments(xcodebuildOutput: xcodeBuildOutput.bridge(), language: .swift,
77 | moduleName: name ?? moduleName(fromArguments: xcodeBuildArguments)) else {
78 | fputs("Could not parse compiler arguments from `xcodebuild` output.\n", stderr)
79 | fputs("Please confirm that `xcodebuild` is building a Swift module.\n", stderr)
80 | let file = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("xcodebuild-\(NSUUID().uuidString).log")
81 | try! xcodeBuildOutput.data(using: .utf8)?.write(to: file)
82 | fputs("Saved `xcodebuild` log file: \(file.path)\n", stderr)
83 | return nil
84 | }
85 | guard let moduleName = moduleName(fromArguments: arguments) else {
86 | fputs("Could not parse module name from compiler arguments.\n", stderr)
87 | return nil
88 | }
89 | self.init(name: moduleName, compilerArguments: arguments)
90 | }
91 |
92 | /**
93 | Initializer to create a Module by name and compiler arguments.
94 |
95 | - parameter name: Module name.
96 | - parameter compilerArguments: Compiler arguments required by SourceKit to process the source files in this Module.
97 | */
98 | public init(name: String, compilerArguments: [String]) {
99 | self.name = name
100 | self.compilerArguments = compilerArguments
101 | sourceFiles = compilerArguments.filter({
102 | $0.bridge().isSwiftFile() && $0.isFile
103 | }).map {
104 | return URL(fileURLWithPath: $0).resolvingSymlinksInPath().path
105 | }
106 | }
107 | }
108 |
109 | // MARK: CustomStringConvertible
110 |
111 | extension Module: CustomStringConvertible {
112 | /// A textual representation of `Module`.
113 | public var description: String {
114 | return "Module(name: \(name), compilerArguments: \(compilerArguments), sourceFiles: \(sourceFiles))"
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/ObjCDeclarationKind.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ObjCDeclarationKind.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 7/15/15.
6 | // Copyright © 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | #if !os(Linux)
10 |
11 | #if SWIFT_PACKAGE
12 | import Clang_C
13 | #endif
14 |
15 | /**
16 | Objective-C declaration kinds.
17 | More or less equivalent to `SwiftDeclarationKind`, but with made up values because there's no such
18 | thing as SourceKit for Objective-C.
19 | */
20 | public enum ObjCDeclarationKind: String {
21 | /// `category`.
22 | case category = "sourcekitten.source.lang.objc.decl.category"
23 | /// `class`.
24 | case `class` = "sourcekitten.source.lang.objc.decl.class"
25 | /// `constant`.
26 | case constant = "sourcekitten.source.lang.objc.decl.constant"
27 | /// `enum`.
28 | case `enum` = "sourcekitten.source.lang.objc.decl.enum"
29 | /// `enumcase`.
30 | case enumcase = "sourcekitten.source.lang.objc.decl.enumcase"
31 | /// `initializer`.
32 | case initializer = "sourcekitten.source.lang.objc.decl.initializer"
33 | /// `method.class`.
34 | case methodClass = "sourcekitten.source.lang.objc.decl.method.class"
35 | /// `method.instance`.
36 | case methodInstance = "sourcekitten.source.lang.objc.decl.method.instance"
37 | /// `property`.
38 | case property = "sourcekitten.source.lang.objc.decl.property"
39 | /// `protocol`.
40 | case `protocol` = "sourcekitten.source.lang.objc.decl.protocol"
41 | /// `typedef`.
42 | case typedef = "sourcekitten.source.lang.objc.decl.typedef"
43 | /// `function`.
44 | case function = "sourcekitten.source.lang.objc.decl.function"
45 | /// `mark`.
46 | case mark = "sourcekitten.source.lang.objc.mark"
47 | /// `struct`
48 | case `struct` = "sourcekitten.source.lang.objc.decl.struct"
49 | /// `field`
50 | case field = "sourcekitten.source.lang.objc.decl.field"
51 | /// `ivar`
52 | case ivar = "sourcekitten.source.lang.objc.decl.ivar"
53 | /// `ModuleImport`
54 | case moduleImport = "sourcekitten.source.lang.objc.module.import"
55 | /// `UnexposedDecl`
56 | case unexposedDecl = "sourcekitten.source.lang.objc.decl.unexposed"
57 |
58 | // swiftlint:disable:next cyclomatic_complexity
59 | public init(_ cursorKind: CXCursorKind) {
60 | switch cursorKind {
61 | case CXCursor_ObjCCategoryDecl: self = .category
62 | case CXCursor_ObjCInterfaceDecl: self = .class
63 | case CXCursor_EnumDecl: self = .enum
64 | case CXCursor_EnumConstantDecl: self = .enumcase
65 | case CXCursor_ObjCClassMethodDecl: self = .methodClass
66 | case CXCursor_ObjCInstanceMethodDecl: self = .methodInstance
67 | case CXCursor_ObjCPropertyDecl: self = .property
68 | case CXCursor_ObjCProtocolDecl: self = .protocol
69 | case CXCursor_TypedefDecl: self = .typedef
70 | case CXCursor_VarDecl: self = .constant
71 | case CXCursor_FunctionDecl: self = .function
72 | case CXCursor_StructDecl: self = .struct
73 | case CXCursor_FieldDecl: self = .field
74 | case CXCursor_ObjCIvarDecl: self = .ivar
75 | case CXCursor_ModuleImportDecl: self = .moduleImport
76 | case CXCursor_UnexposedDecl: self = .unexposedDecl
77 | default: fatalError("Unsupported CXCursorKind: \(clang_getCursorKindSpelling(cursorKind))")
78 | }
79 | }
80 | }
81 | #endif
82 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/OffsetMap.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OffsetMap.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-05.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | /// Type that maps potentially documented declaration offsets to its closest parent offset.
10 | public typealias OffsetMap = [Int: Int]
11 |
12 | /// File methods to generate and manipulate OffsetMap's.
13 | extension File {
14 | /**
15 | Creates an OffsetMap containing offset locations at which there are declarations that likely
16 | have documentation comments, but haven't been documented by SourceKitten yet.
17 |
18 | - parameter documentedTokenOffsets: Offsets where there are declarations that likely
19 | have documentation comments.
20 | - parameter dictionary: Docs dictionary to check for which offsets are already
21 | documented.
22 |
23 | - returns: OffsetMap containing offset locations at which there are declarations that likely
24 | have documentation comments, but haven't been documented by SourceKitten yet.
25 | */
26 | public func makeOffsetMap(documentedTokenOffsets: [Int], dictionary: [String: SourceKitRepresentable]) -> OffsetMap {
27 | var offsetMap = OffsetMap()
28 | for offset in documentedTokenOffsets {
29 | offsetMap[offset] = 0
30 | }
31 | offsetMap = mapOffsets(dictionary, offsetMap: offsetMap)
32 | let alreadyDocumentedOffsets = offsetMap.filter({ $0.0 == $0.1 }).map { $0.0 }
33 | for alreadyDocumentedOffset in alreadyDocumentedOffsets {
34 | offsetMap.removeValue(forKey: alreadyDocumentedOffset)
35 | }
36 | return offsetMap
37 | }
38 |
39 | /**
40 | Creates a new OffsetMap that matches all offsets in the offsetMap parameter's keys to its
41 | nearest, currently documented parent offset.
42 |
43 | - parameter dictionary: Already documented dictionary.
44 | - parameter offsetMap: Dictionary mapping potentially documented offsets to its nearest parent
45 | offset.
46 |
47 | - returns: OffsetMap of potentially documented declaration offsets to its nearest parent offset.
48 | */
49 | private func mapOffsets(_ dictionary: [String: SourceKitRepresentable], offsetMap: OffsetMap) -> OffsetMap {
50 | var offsetMap = offsetMap
51 | if let rangeStart = SwiftDocKey.getNameOffset(dictionary),
52 | let rangeLength = SwiftDocKey.getNameLength(dictionary) {
53 | let bodyLength = SwiftDocKey.getBodyLength(dictionary) ?? 0
54 | let rangeMax = Int(rangeStart + rangeLength + bodyLength)
55 | let rangeStart = Int(rangeStart)
56 | let offsetsInRange = offsetMap.keys.filter {
57 | $0 >= rangeStart && $0 <= rangeMax
58 | }
59 | for offset in offsetsInRange {
60 | offsetMap[offset] = rangeStart
61 | }
62 | }
63 | // Recurse!
64 | if let substructure = SwiftDocKey.getSubstructure(dictionary) {
65 | for subDict in substructure {
66 | offsetMap = mapOffsets(subDict as! [String: SourceKitRepresentable], offsetMap: offsetMap)
67 | }
68 | }
69 | return offsetMap
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Parameter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Parameter.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 10/27/15.
6 | // Copyright © 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | #if !os(Linux)
10 |
11 | #if SWIFT_PACKAGE
12 | import Clang_C
13 | #endif
14 |
15 | public struct Parameter {
16 | public let name: String
17 | public let discussion: [Text]
18 |
19 | init(comment: CXComment) {
20 | name = comment.paramName() ?? ""
21 | discussion = comment.paragraph().paragraphToString()
22 | }
23 | }
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/SourceLocation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceLocation.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 10/27/15.
6 | // Copyright © 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | #if !os(Linux)
10 |
11 | #if SWIFT_PACKAGE
12 | import Clang_C
13 | #endif
14 | import Foundation
15 |
16 | public struct SourceLocation {
17 | public let file: String
18 | public let line: UInt32
19 | public let column: UInt32
20 | public let offset: UInt32
21 |
22 | public func range(toEnd end: SourceLocation) -> NSRange {
23 | return NSRange(location: Int(offset), length: Int(end.offset - offset))
24 | }
25 | }
26 |
27 | extension SourceLocation {
28 | init(clangLocation: CXSourceLocation) {
29 | var cxfile: CXFile? = nil
30 | var line: UInt32 = 0
31 | var column: UInt32 = 0
32 | var offset: UInt32 = 0
33 | clang_getSpellingLocation(clangLocation, &cxfile, &line, &column, &offset)
34 | self.init(file: clang_getFileName(cxfile).str() ?? "",
35 | line: line, column: column, offset: offset)
36 | }
37 | }
38 |
39 | // MARK: Comparable
40 |
41 | extension SourceLocation: Comparable {}
42 |
43 | public func == (lhs: SourceLocation, rhs: SourceLocation) -> Bool {
44 | return lhs.file.compare(rhs.file) == .orderedSame &&
45 | lhs.line == rhs.line &&
46 | lhs.column == rhs.column &&
47 | lhs.offset == rhs.offset
48 | }
49 |
50 | /// A [strict total order](http://en.wikipedia.org/wiki/Total_order#Strict_total_order)
51 | /// over instances of `Self`.
52 | public func < (lhs: SourceLocation, rhs: SourceLocation) -> Bool {
53 | // Sort by file path.
54 | switch lhs.file.compare(rhs.file) {
55 | case .orderedDescending:
56 | return false
57 | case .orderedAscending:
58 | return true
59 | case .orderedSame:
60 | break
61 | }
62 |
63 | // Then offset.
64 | return lhs.offset < rhs.offset
65 | }
66 | #endif
67 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/StatementKind.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftStatementKind.swift
3 | // SourceKitten
4 | //
5 | // Created by Denis Lebedev on 03/02/2016.
6 | // Copyright © 2016 SourceKitten. All rights reserved.
7 | //
8 |
9 | // swiftlint:disable identifier_name
10 |
11 | /// Swift declaration kinds.
12 | /// Found in `strings SourceKitService | grep source.lang.swift.stmt.`.
13 | public enum StatementKind: String, SwiftLangSyntax {
14 | /// `brace`.
15 | case brace = "source.lang.swift.stmt.brace"
16 | /// `case`.
17 | case `case` = "source.lang.swift.stmt.case"
18 | /// `for`.
19 | case `for` = "source.lang.swift.stmt.for"
20 | /// `foreach`.
21 | case forEach = "source.lang.swift.stmt.foreach"
22 | /// `guard`.
23 | case `guard` = "source.lang.swift.stmt.guard"
24 | /// `if`.
25 | case `if` = "source.lang.swift.stmt.if"
26 | /// `repeatewhile`.
27 | case repeatWhile = "source.lang.swift.stmt.repeatwhile"
28 | /// `switch`.
29 | case `switch` = "source.lang.swift.stmt.switch"
30 | /// `while`.
31 | case `while` = "source.lang.swift.stmt.while"
32 | }
33 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Structure.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Structure.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-06.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// Represents the structural information in a Swift source file.
12 | public struct Structure {
13 | /// Structural information as an [String: SourceKitRepresentable].
14 | public let dictionary: [String: SourceKitRepresentable]
15 |
16 | /**
17 | Create a Structure from a SourceKit `editor.open` response.
18 |
19 | - parameter sourceKitResponse: SourceKit `editor.open` response.
20 | */
21 | public init(sourceKitResponse: [String: SourceKitRepresentable]) {
22 | var sourceKitResponse = sourceKitResponse
23 | _ = sourceKitResponse.removeValue(forKey: SwiftDocKey.syntaxMap.rawValue)
24 | dictionary = sourceKitResponse
25 | }
26 |
27 | /**
28 | Initialize a Structure by passing in a File.
29 |
30 | - parameter file: File to parse for structural information.
31 | - throws: Request.Error
32 | */
33 | public init(file: File) throws {
34 | self.init(sourceKitResponse: try Request.editorOpen(file: file).send())
35 | }
36 | }
37 |
38 | // MARK: CustomStringConvertible
39 |
40 | extension Structure: CustomStringConvertible {
41 | /// A textual JSON representation of `Structure`.
42 | public var description: String { return toJSON(toNSDictionary(dictionary)) }
43 | }
44 |
45 | // MARK: Equatable
46 |
47 | extension Structure: Equatable {}
48 |
49 | /**
50 | Returns true if `lhs` Structure is equal to `rhs` Structure.
51 |
52 | - parameter lhs: Structure to compare to `rhs`.
53 | - parameter rhs: Structure to compare to `lhs`.
54 |
55 | - returns: True if `lhs` Structure is equal to `rhs` Structure.
56 | */
57 | public func == (lhs: Structure, rhs: Structure) -> Bool {
58 | return lhs.dictionary.isEqualTo(rhs.dictionary)
59 | }
60 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/SwiftDeclarationKind.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftDeclarationKind.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-05.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | /// Swift declaration kinds.
10 | /// Found in `strings SourceKitService | grep source.lang.swift.decl.`.
11 | public enum SwiftDeclarationKind: String, SwiftLangSyntax {
12 | /// `associatedtype`.
13 | case `associatedtype` = "source.lang.swift.decl.associatedtype"
14 | /// `class`.
15 | case `class` = "source.lang.swift.decl.class"
16 | /// `enum`.
17 | case `enum` = "source.lang.swift.decl.enum"
18 | /// `enumcase`.
19 | case enumcase = "source.lang.swift.decl.enumcase"
20 | /// `enumelement`.
21 | case enumelement = "source.lang.swift.decl.enumelement"
22 | /// `extension`.
23 | case `extension` = "source.lang.swift.decl.extension"
24 | /// `extension.class`.
25 | case extensionClass = "source.lang.swift.decl.extension.class"
26 | /// `extension.enum`.
27 | case extensionEnum = "source.lang.swift.decl.extension.enum"
28 | /// `extension.protocol`.
29 | case extensionProtocol = "source.lang.swift.decl.extension.protocol"
30 | /// `extension.struct`.
31 | case extensionStruct = "source.lang.swift.decl.extension.struct"
32 | /// `function.accessor.address`.
33 | case functionAccessorAddress = "source.lang.swift.decl.function.accessor.address"
34 | /// `function.accessor.didset`.
35 | case functionAccessorDidset = "source.lang.swift.decl.function.accessor.didset"
36 | /// `function.accessor.getter`.
37 | case functionAccessorGetter = "source.lang.swift.decl.function.accessor.getter"
38 | /// `function.accessor.mutableaddress`.
39 | case functionAccessorMutableaddress = "source.lang.swift.decl.function.accessor.mutableaddress"
40 | /// `function.accessor.setter`.
41 | case functionAccessorSetter = "source.lang.swift.decl.function.accessor.setter"
42 | /// `function.accessor.willset`.
43 | case functionAccessorWillset = "source.lang.swift.decl.function.accessor.willset"
44 | /// `function.constructor`.
45 | case functionConstructor = "source.lang.swift.decl.function.constructor"
46 | /// `function.destructor`.
47 | case functionDestructor = "source.lang.swift.decl.function.destructor"
48 | /// `function.free`.
49 | case functionFree = "source.lang.swift.decl.function.free"
50 | /// `function.method.class`.
51 | case functionMethodClass = "source.lang.swift.decl.function.method.class"
52 | /// `function.method.instance`.
53 | case functionMethodInstance = "source.lang.swift.decl.function.method.instance"
54 | /// `function.method.static`.
55 | case functionMethodStatic = "source.lang.swift.decl.function.method.static"
56 | /// `function.operator`.
57 | case functionOperator = "source.lang.swift.decl.function.operator"
58 | /// `function.operator.infix`.
59 | case functionOperatorInfix = "source.lang.swift.decl.function.operator.infix"
60 | /// `function.operator.postfix`.
61 | case functionOperatorPostfix = "source.lang.swift.decl.function.operator.postfix"
62 | /// `function.operator.prefix`.
63 | case functionOperatorPrefix = "source.lang.swift.decl.function.operator.prefix"
64 | /// `function.subscript`.
65 | case functionSubscript = "source.lang.swift.decl.function.subscript"
66 | /// `generic_type_param`.
67 | case genericTypeParam = "source.lang.swift.decl.generic_type_param"
68 | /// `module`.
69 | case module = "source.lang.swift.decl.module"
70 | /// `precedencegroup`.
71 | case precedenceGroup = "source.lang.swift.decl.precedencegroup"
72 | /// `protocol`.
73 | case `protocol` = "source.lang.swift.decl.protocol"
74 | /// `struct`.
75 | case `struct` = "source.lang.swift.decl.struct"
76 | /// `typealias`.
77 | case `typealias` = "source.lang.swift.decl.typealias"
78 | /// `var.class`.
79 | case varClass = "source.lang.swift.decl.var.class"
80 | /// `var.global`.
81 | case varGlobal = "source.lang.swift.decl.var.global"
82 | /// `var.instance`.
83 | case varInstance = "source.lang.swift.decl.var.instance"
84 | /// `var.local`.
85 | case varLocal = "source.lang.swift.decl.var.local"
86 | /// `var.parameter`.
87 | case varParameter = "source.lang.swift.decl.var.parameter"
88 | /// `var.static`.
89 | case varStatic = "source.lang.swift.decl.var.static"
90 | }
91 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/SwiftDocs.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftDocs.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-03.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | #if SWIFT_PACKAGE
11 | import SourceKit
12 | #endif
13 |
14 | /// Represents docs for a Swift file.
15 | public struct SwiftDocs {
16 | /// Documented File.
17 | public let file: File
18 |
19 | /// Docs information as an [String: SourceKitRepresentable].
20 | public let docsDictionary: [String: SourceKitRepresentable]
21 |
22 | /**
23 | Create docs for the specified Swift file and compiler arguments.
24 |
25 | - parameter file: Swift file to document.
26 | - parameter arguments: compiler arguments to pass to SourceKit.
27 | */
28 | public init?(file: File, arguments: [String]) {
29 | do {
30 | self.init(
31 | file: file,
32 | dictionary: try Request.editorOpen(file: file).send(),
33 | cursorInfoRequest: Request.cursorInfoRequest(filePath: file.path, arguments: arguments)
34 | )
35 | } catch let error as Request.Error {
36 | fputs(error.description, stderr)
37 | return nil
38 | } catch {
39 | return nil
40 | }
41 | }
42 |
43 | /**
44 | Create docs for the specified Swift file, editor.open SourceKit response and cursor info request.
45 |
46 | - parameter file: Swift file to document.
47 | - parameter dictionary: editor.open response from SourceKit.
48 | - parameter cursorInfoRequest: SourceKit dictionary to use to send cursorinfo request.
49 | */
50 | public init(file: File, dictionary: [String: SourceKitRepresentable], cursorInfoRequest: sourcekitd_object_t?) {
51 | self.file = file
52 | var dictionary = dictionary
53 | let syntaxMapData = dictionary.removeValue(forKey: SwiftDocKey.syntaxMap.rawValue) as! [SourceKitRepresentable]
54 | let syntaxMap = SyntaxMap(data: syntaxMapData)
55 | dictionary = file.process(dictionary: dictionary, cursorInfoRequest: cursorInfoRequest, syntaxMap: syntaxMap)
56 | if let cursorInfoRequest = cursorInfoRequest {
57 | let documentedTokenOffsets = file.contents.documentedTokenOffsets(syntaxMap: syntaxMap)
58 | dictionary = file.furtherProcess(
59 | dictionary: dictionary,
60 | documentedTokenOffsets: documentedTokenOffsets,
61 | cursorInfoRequest: cursorInfoRequest,
62 | syntaxMap: syntaxMap
63 | )
64 | }
65 | docsDictionary = file.addDocComments(dictionary: dictionary, syntaxMap: syntaxMap)
66 | }
67 | }
68 |
69 | // MARK: CustomStringConvertible
70 |
71 | extension SwiftDocs: CustomStringConvertible {
72 | /// A textual JSON representation of `SwiftDocs`.
73 | public var description: String {
74 | return toJSON(toNSDictionary([file.path ?? "": docsDictionary]))
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/SwiftLangSyntax.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public protocol SwiftLangSyntax {
4 | var rawValue: String { get }
5 | }
6 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/SyntaxKind.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SyntaxKind.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-03.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | /// Syntax kind values.
10 | /// Found in `strings SourceKitService | grep source.lang.swift.syntaxtype.`.
11 | public enum SyntaxKind: String, SwiftLangSyntax {
12 | /// `argument`.
13 | case argument = "source.lang.swift.syntaxtype.argument"
14 | /// `attribute.builtin`.
15 | case attributeBuiltin = "source.lang.swift.syntaxtype.attribute.builtin"
16 | /// `attribute.id`.
17 | case attributeID = "source.lang.swift.syntaxtype.attribute.id"
18 | /// `buildconfig.id`.
19 | case buildconfigID = "source.lang.swift.syntaxtype.buildconfig.id"
20 | /// `buildconfig.keyword`.
21 | case buildconfigKeyword = "source.lang.swift.syntaxtype.buildconfig.keyword"
22 | /// `comment`.
23 | case comment = "source.lang.swift.syntaxtype.comment"
24 | /// `comment.mark`.
25 | case commentMark = "source.lang.swift.syntaxtype.comment.mark"
26 | /// `comment.url`.
27 | case commentURL = "source.lang.swift.syntaxtype.comment.url"
28 | /// `doccomment`.
29 | case docComment = "source.lang.swift.syntaxtype.doccomment"
30 | /// `doccomment.field`.
31 | case docCommentField = "source.lang.swift.syntaxtype.doccomment.field"
32 | /// `identifier`.
33 | case identifier = "source.lang.swift.syntaxtype.identifier"
34 | /// `keyword`.
35 | case keyword = "source.lang.swift.syntaxtype.keyword"
36 | /// `number`.
37 | case number = "source.lang.swift.syntaxtype.number"
38 | /// `objectliteral`
39 | case objectLiteral = "source.lang.swift.syntaxtype.objectliteral"
40 | /// `parameter`.
41 | case parameter = "source.lang.swift.syntaxtype.parameter"
42 | /// `placeholder`.
43 | case placeholder = "source.lang.swift.syntaxtype.placeholder"
44 | /// `string`.
45 | case string = "source.lang.swift.syntaxtype.string"
46 | /// `string_interpolation_anchor`.
47 | case stringInterpolationAnchor = "source.lang.swift.syntaxtype.string_interpolation_anchor"
48 | /// `typeidentifier`.
49 | case typeidentifier = "source.lang.swift.syntaxtype.typeidentifier"
50 |
51 | /// Returns the valid documentation comment syntax kinds.
52 | internal static func docComments() -> [SyntaxKind] {
53 | return [.commentURL, .docComment, .docCommentField]
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/SyntaxMap.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SyntaxMap.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-03.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// Represents a Swift file's syntax information.
12 | public struct SyntaxMap {
13 | /// Array of SyntaxToken's.
14 | public let tokens: [SyntaxToken]
15 |
16 | /**
17 | Create a SyntaxMap by passing in tokens directly.
18 |
19 | - parameter tokens: Array of SyntaxToken's.
20 | */
21 | public init(tokens: [SyntaxToken]) {
22 | self.tokens = tokens
23 | }
24 |
25 | /**
26 | Create a SyntaxMap by passing in NSData from a SourceKit `editor.open` response to be parsed.
27 |
28 | - parameter data: NSData from a SourceKit `editor.open` response
29 | */
30 | public init(data: [SourceKitRepresentable]) {
31 | tokens = data.map { item in
32 | let dict = item as! [String: SourceKitRepresentable]
33 | return SyntaxToken(type: dict["key.kind"] as! String, offset: Int(dict["key.offset"] as! Int64), length: Int(dict["key.length"] as! Int64))
34 | }
35 | }
36 |
37 | /**
38 | Create a SyntaxMap from a SourceKit `editor.open` response.
39 |
40 | - parameter sourceKitResponse: SourceKit `editor.open` response.
41 | */
42 | public init(sourceKitResponse: [String: SourceKitRepresentable]) {
43 | self.init(data: SwiftDocKey.getSyntaxMap(sourceKitResponse)!)
44 | }
45 |
46 | /**
47 | Create a SyntaxMap from a File to be parsed.
48 |
49 | - parameter file: File to be parsed.
50 | - throws: Request.Error
51 | */
52 | public init(file: File) throws {
53 | self.init(sourceKitResponse: try Request.editorOpen(file: file).send())
54 | }
55 | }
56 |
57 | // MARK: Support for enumerating doc-comment blocks
58 |
59 | extension SyntaxToken {
60 | /// Is this a doc comment?
61 | internal var isDocComment: Bool {
62 | return SyntaxKind.docComments().contains { $0.rawValue == type }
63 | }
64 | }
65 |
66 | extension SyntaxMap {
67 | /// The ranges of documentation comments described by the map, in the order
68 | /// that they occur in the file.
69 | internal var docCommentRanges: [Range] {
70 | let docCommentBlocks = tokens.split { !$0.isDocComment }
71 | return docCommentBlocks.flatMap { ranges in
72 | ranges.first.flatMap { first in
73 | ranges.last.flatMap { last -> Range? in
74 | first.offset..]
89 | /// The most recent file offset requested
90 | private var previousOffset: Int
91 |
92 | /// Create a new doc comment finder from a `SyntaxMap`.
93 | internal init(syntaxMap: SyntaxMap) {
94 | self.ranges = syntaxMap.docCommentRanges
95 | self.previousOffset = -1
96 | }
97 |
98 | /// Get the byte range of the declaration's doc comment, or nil if none.
99 | internal func getRangeForDeclaration(atOffset offset: Int) -> Range? {
100 | guard offset > previousOffset else { return nil }
101 |
102 | let commentsBeforeDecl = ranges.prefix { $0.upperBound < offset }
103 | ranges.replaceSubrange(0.. DocCommentFinder {
111 | return DocCommentFinder(syntaxMap: self)
112 | }
113 | }
114 |
115 | // MARK: CustomStringConvertible
116 |
117 | extension SyntaxMap: CustomStringConvertible {
118 | /// A textual JSON representation of `SyntaxMap`.
119 | public var description: String {
120 | return toJSON(tokens.map { $0.dictionaryValue })
121 | }
122 | }
123 |
124 | // MARK: Equatable
125 |
126 | extension SyntaxMap: Equatable {}
127 |
128 | /**
129 | Returns true if `lhs` SyntaxMap is equal to `rhs` SyntaxMap.
130 |
131 | - parameter lhs: SyntaxMap to compare to `rhs`.
132 | - parameter rhs: SyntaxMap to compare to `lhs`.
133 |
134 | - returns: True if `lhs` SyntaxMap is equal to `rhs` SyntaxMap.
135 | */
136 | public func == (lhs: SyntaxMap, rhs: SyntaxMap) -> Bool {
137 | if lhs.tokens.count != rhs.tokens.count {
138 | return false
139 | }
140 | for (index, value) in lhs.tokens.enumerated() where rhs.tokens[index] != value {
141 | return false
142 | }
143 | return true
144 | }
145 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/SyntaxToken.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SyntaxToken.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2015-01-03.
6 | // Copyright (c) 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | /// Represents a single Swift syntax token.
10 | public struct SyntaxToken {
11 | /// Token type. See SyntaxKind.
12 | public let type: String
13 | /// Token offset.
14 | public let offset: Int
15 | /// Token length.
16 | public let length: Int
17 |
18 | /// Dictionary representation of SyntaxToken. Useful for NSJSONSerialization.
19 | public var dictionaryValue: [String: Any] {
20 | return ["type": type, "offset": offset, "length": length]
21 | }
22 |
23 | /**
24 | Create a SyntaxToken by directly passing in its property values.
25 |
26 | - parameter type: Token type. See SyntaxKind.
27 | - parameter offset: Token offset.
28 | - parameter length: Token length.
29 | */
30 | public init(type: String, offset: Int, length: Int) {
31 | self.type = SyntaxKind(rawValue: type)?.rawValue ?? type
32 | self.offset = offset
33 | self.length = length
34 | }
35 | }
36 |
37 | // MARK: Equatable
38 |
39 | extension SyntaxToken: Equatable {}
40 |
41 | /**
42 | Returns true if `lhs` SyntaxToken is equal to `rhs` SyntaxToken.
43 |
44 | - parameter lhs: SyntaxToken to compare to `rhs`.
45 | - parameter rhs: SyntaxToken to compare to `lhs`.
46 |
47 | - returns: True if `lhs` SyntaxToken is equal to `rhs` SyntaxToken.
48 | */
49 | public func == (lhs: SyntaxToken, rhs: SyntaxToken) -> Bool {
50 | return (lhs.type == rhs.type) && (lhs.offset == rhs.offset) && (lhs.length == rhs.length)
51 | }
52 |
53 | // MARK: CustomStringConvertible
54 |
55 | extension SyntaxToken: CustomStringConvertible {
56 | /// A textual JSON representation of `SyntaxToken`.
57 | public var description: String { return toJSON(dictionaryValue.bridge()) }
58 | }
59 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Text.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Text.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 10/27/15.
6 | // Copyright © 2015 SourceKitten. All rights reserved.
7 | //
8 |
9 | public enum Text {
10 | case para(String, String?)
11 | case verbatim(String)
12 | }
13 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/Version.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VersionCommand.swift
3 | // SourceKitten
4 | //
5 | // Created by JP Simard on 2017-05-15.
6 | // Copyright (c) 2017 SourceKitten. All rights reserved.
7 | //
8 |
9 | public struct Version {
10 | public let value: String
11 |
12 | public static let current = Version(value: "0.19.1")
13 | }
14 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/clang-c/CXErrorCode.h:
--------------------------------------------------------------------------------
1 | /*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- C -*-===*\
2 | |* *|
3 | |* The LLVM Compiler Infrastructure *|
4 | |* *|
5 | |* This file is distributed under the University of Illinois Open Source *|
6 | |* License. See LICENSE.TXT for details. *|
7 | |* *|
8 | |*===----------------------------------------------------------------------===*|
9 | |* *|
10 | |* This header provides the CXErrorCode enumerators. *|
11 | |* *|
12 | \*===----------------------------------------------------------------------===*/
13 |
14 | #ifndef LLVM_CLANG_C_CXERRORCODE_H
15 | #define LLVM_CLANG_C_CXERRORCODE_H
16 |
17 | #import
18 |
19 | #ifdef __cplusplus
20 | extern "C" {
21 | #endif
22 |
23 | /**
24 | * \brief Error codes returned by libclang routines.
25 | *
26 | * Zero (\c CXError_Success) is the only error code indicating success. Other
27 | * error codes, including not yet assigned non-zero values, indicate errors.
28 | */
29 | enum CXErrorCode {
30 | /**
31 | * \brief No error.
32 | */
33 | CXError_Success = 0,
34 |
35 | /**
36 | * \brief A generic error code, no further details are available.
37 | *
38 | * Errors of this kind can get their own specific error codes in future
39 | * libclang versions.
40 | */
41 | CXError_Failure = 1,
42 |
43 | /**
44 | * \brief libclang crashed while performing the requested operation.
45 | */
46 | CXError_Crashed = 2,
47 |
48 | /**
49 | * \brief The function detected that the arguments violate the function
50 | * contract.
51 | */
52 | CXError_InvalidArguments = 3,
53 |
54 | /**
55 | * \brief An AST deserialization error has occurred.
56 | */
57 | CXError_ASTReadError = 4
58 | };
59 |
60 | #ifdef __cplusplus
61 | }
62 | #endif
63 | #endif
64 |
65 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/clang-c/CXString.h:
--------------------------------------------------------------------------------
1 | /*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\
2 | |* *|
3 | |* The LLVM Compiler Infrastructure *|
4 | |* *|
5 | |* This file is distributed under the University of Illinois Open Source *|
6 | |* License. See LICENSE.TXT for details. *|
7 | |* *|
8 | |*===----------------------------------------------------------------------===*|
9 | |* *|
10 | |* This header provides the interface to C Index strings. *|
11 | |* *|
12 | \*===----------------------------------------------------------------------===*/
13 |
14 | #ifndef LLVM_CLANG_C_CXSTRING_H
15 | #define LLVM_CLANG_C_CXSTRING_H
16 |
17 | #import
18 |
19 | #ifdef __cplusplus
20 | extern "C" {
21 | #endif
22 |
23 | /**
24 | * \defgroup CINDEX_STRING String manipulation routines
25 | * \ingroup CINDEX
26 | *
27 | * @{
28 | */
29 |
30 | /**
31 | * \brief A character string.
32 | *
33 | * The \c CXString type is used to return strings from the interface when
34 | * the ownership of that string might differ from one call to the next.
35 | * Use \c clang_getCString() to retrieve the string data and, once finished
36 | * with the string data, call \c clang_disposeString() to free the string.
37 | */
38 | typedef struct {
39 | const void *data;
40 | unsigned private_flags;
41 | } CXString;
42 |
43 | /**
44 | * \brief Retrieve the character data associated with the given string.
45 | */
46 | CINDEX_LINKAGE const char *clang_getCString(CXString string);
47 |
48 | /**
49 | * \brief Free the given string.
50 | */
51 | CINDEX_LINKAGE void clang_disposeString(CXString string);
52 |
53 | /**
54 | * @}
55 | */
56 |
57 | #ifdef __cplusplus
58 | }
59 | #endif
60 | #endif
61 |
62 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/clang-c/Platform.h:
--------------------------------------------------------------------------------
1 | /*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\
2 | |* *|
3 | |* The LLVM Compiler Infrastructure *|
4 | |* *|
5 | |* This file is distributed under the University of Illinois Open Source *|
6 | |* License. See LICENSE.TXT for details. *|
7 | |* *|
8 | |*===----------------------------------------------------------------------===*|
9 | |* *|
10 | |* This header provides platform specific macros (dllimport, deprecated, ...) *|
11 | |* *|
12 | \*===----------------------------------------------------------------------===*/
13 |
14 | #ifndef LLVM_CLANG_C_PLATFORM_H
15 | #define LLVM_CLANG_C_PLATFORM_H
16 |
17 | #ifdef __cplusplus
18 | extern "C" {
19 | #endif
20 |
21 | /* MSVC DLL import/export. */
22 | #ifdef _MSC_VER
23 | #ifdef _CINDEX_LIB_
24 | #define CINDEX_LINKAGE __declspec(dllexport)
25 | #else
26 | #define CINDEX_LINKAGE __declspec(dllimport)
27 | #endif
28 | #else
29 | #define CINDEX_LINKAGE
30 | #endif
31 |
32 | #ifdef __GNUC__
33 | #define CINDEX_DEPRECATED __attribute__((deprecated))
34 | #else
35 | #ifdef _MSC_VER
36 | #define CINDEX_DEPRECATED __declspec(deprecated)
37 | #else
38 | #define CINDEX_DEPRECATED
39 | #endif
40 | #endif
41 |
42 | #ifdef __cplusplus
43 | }
44 | #endif
45 | #endif
46 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/library_wrapper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // library_wrapper.swift
3 | // sourcekitten
4 | //
5 | // Created by Norio Nomura on 2/20/16.
6 | // Copyright © 2016 SourceKitten. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct DynamicLinkLibrary {
12 | let path: String
13 | let handle: UnsafeMutableRawPointer
14 |
15 | func load(symbol: String) -> T {
16 | if let sym = dlsym(handle, symbol) {
17 | return unsafeBitCast(sym, to: T.self)
18 | }
19 | let errorString = String(validatingUTF8: dlerror())
20 | fatalError("Finding symbol \(symbol) failed: \(errorString ?? "unknown error")")
21 | }
22 | }
23 |
24 | #if os(Linux)
25 | let toolchainLoader = Loader(searchPaths: [linuxSourceKitLibPath])
26 | #else
27 | let toolchainLoader = Loader(searchPaths: [
28 | xcodeDefaultToolchainOverride,
29 | toolchainDir,
30 | xcrunFindPath,
31 | /*
32 | These search paths are used when `xcode-select -p` points to
33 | "Command Line Tools OS X for Xcode", but Xcode.app exists.
34 | */
35 | applicationsDir?.xcodeDeveloperDir.toolchainDir,
36 | applicationsDir?.xcodeBetaDeveloperDir.toolchainDir,
37 | userApplicationsDir?.xcodeDeveloperDir.toolchainDir,
38 | userApplicationsDir?.xcodeBetaDeveloperDir.toolchainDir
39 | ].flatMap { path in
40 | if let fullPath = path?.usrLibDir, fullPath.isFile {
41 | return fullPath
42 | }
43 | return nil
44 | })
45 | #endif
46 |
47 | struct Loader {
48 | let searchPaths: [String]
49 |
50 | func load(path: String) -> DynamicLinkLibrary {
51 | let fullPaths = searchPaths.map { $0.appending(pathComponent: path) }.filter { $0.isFile }
52 |
53 | // try all fullPaths that contains target file,
54 | // then try loading with simple path that depends resolving to DYLD
55 | for fullPath in fullPaths + [path] {
56 | if let handle = dlopen(fullPath, RTLD_LAZY) {
57 | return DynamicLinkLibrary(path: path, handle: handle)
58 | }
59 | }
60 |
61 | fatalError("Loading \(path) failed")
62 | }
63 | }
64 |
65 | private func env(_ name: String) -> String? {
66 | return ProcessInfo.processInfo.environment[name]
67 | }
68 |
69 | /// Returns "LINUX_SOURCEKIT_LIB_PATH" environment variable,
70 | /// or "/usr/lib" if unspecified.
71 | internal let linuxSourceKitLibPath = env("LINUX_SOURCEKIT_LIB_PATH") ?? "/usr/lib"
72 |
73 | /// Returns "XCODE_DEFAULT_TOOLCHAIN_OVERRIDE" environment variable
74 | ///
75 | /// `launch-with-toolchain` sets the toolchain path to the
76 | /// "XCODE_DEFAULT_TOOLCHAIN_OVERRIDE" environment variable.
77 | private let xcodeDefaultToolchainOverride = env("XCODE_DEFAULT_TOOLCHAIN_OVERRIDE")
78 |
79 | /// Returns "TOOLCHAIN_DIR" environment variable
80 | ///
81 | /// `Xcode`/`xcodebuild` sets the toolchain path to the
82 | /// "TOOLCHAIN_DIR" environment variable.
83 | private let toolchainDir = env("TOOLCHAIN_DIR")
84 |
85 | /// Returns toolchain directory that parsed from result of `xcrun -find swift`
86 | ///
87 | /// This is affected by "DEVELOPER_DIR", "TOOLCHAINS" environment variables.
88 | private let xcrunFindPath: String? = {
89 | let pathOfXcrun = "/usr/bin/xcrun"
90 |
91 | if !FileManager.default.isExecutableFile(atPath: pathOfXcrun) {
92 | return nil
93 | }
94 |
95 | let task = Process()
96 | task.launchPath = pathOfXcrun
97 | task.arguments = ["-find", "swift"]
98 |
99 | let pipe = Pipe()
100 | task.standardOutput = pipe
101 | task.launch() // if xcode-select does not exist, crash with `NSInvalidArgumentException`.
102 |
103 | let data = pipe.fileHandleForReading.readDataToEndOfFile()
104 | guard let output = String(data: data, encoding: .utf8) else {
105 | return nil
106 | }
107 |
108 | var start = output.startIndex
109 | var end = output.startIndex
110 | var contentsEnd = output.startIndex
111 | output.getLineStart(&start, end: &end, contentsEnd: &contentsEnd, for: start..=4.0)
113 | let xcrunFindSwiftPath = String(output[start.. String {
153 | return URL(fileURLWithPath: self).appendingPathComponent(pathComponent).path
154 | }
155 |
156 | func deleting(lastPathComponents numberOfPathComponents: Int) -> String {
157 | var url = URL(fileURLWithPath: self)
158 | for _ in 0.. (UnsafePointer?) = library.load(symbol: "clang_getCString")
7 | internal let clang_disposeString: @convention(c) (CXString) -> () = library.load(symbol: "clang_disposeString")
8 | #endif
9 |
--------------------------------------------------------------------------------
/Pods/SourceKittenFramework/Source/SourceKittenFramework/library_wrapper_Documentation.swift:
--------------------------------------------------------------------------------
1 | #if !os(Linux)
2 | #if SWIFT_PACKAGE
3 | import Clang_C
4 | #endif
5 | private let library = toolchainLoader.load(path: "libclang.dylib")
6 | internal let clang_Cursor_getParsedComment: @convention(c) (CXCursor) -> (CXComment) = library.load(symbol: "clang_Cursor_getParsedComment")
7 | internal let clang_Comment_getKind: @convention(c) (CXComment) -> (CXCommentKind) = library.load(symbol: "clang_Comment_getKind")
8 | internal let clang_Comment_getNumChildren: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_Comment_getNumChildren")
9 | internal let clang_Comment_getChild: @convention(c) (CXComment, UInt32) -> (CXComment) = library.load(symbol: "clang_Comment_getChild")
10 | internal let clang_Comment_isWhitespace: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_Comment_isWhitespace")
11 | internal let clang_InlineContentComment_hasTrailingNewline: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_InlineContentComment_hasTrailingNewline")
12 | internal let clang_TextComment_getText: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_TextComment_getText")
13 | internal let clang_InlineCommandComment_getCommandName: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_InlineCommandComment_getCommandName")
14 | internal let clang_InlineCommandComment_getRenderKind: @convention(c) (CXComment) -> (CXCommentInlineCommandRenderKind) = library.load(symbol: "clang_InlineCommandComment_getRenderKind")
15 | internal let clang_InlineCommandComment_getNumArgs: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_InlineCommandComment_getNumArgs")
16 | internal let clang_InlineCommandComment_getArgText: @convention(c) (CXComment, UInt32) -> (CXString) = library.load(symbol: "clang_InlineCommandComment_getArgText")
17 | internal let clang_HTMLTagComment_getTagName: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_HTMLTagComment_getTagName")
18 | internal let clang_HTMLStartTagComment_isSelfClosing: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_HTMLStartTagComment_isSelfClosing")
19 | internal let clang_HTMLStartTag_getNumAttrs: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_HTMLStartTag_getNumAttrs")
20 | internal let clang_HTMLStartTag_getAttrName: @convention(c) (CXComment, UInt32) -> (CXString) = library.load(symbol: "clang_HTMLStartTag_getAttrName")
21 | internal let clang_HTMLStartTag_getAttrValue: @convention(c) (CXComment, UInt32) -> (CXString) = library.load(symbol: "clang_HTMLStartTag_getAttrValue")
22 | internal let clang_BlockCommandComment_getCommandName: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_BlockCommandComment_getCommandName")
23 | internal let clang_BlockCommandComment_getNumArgs: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_BlockCommandComment_getNumArgs")
24 | internal let clang_BlockCommandComment_getArgText: @convention(c) (CXComment, UInt32) -> (CXString) = library.load(symbol: "clang_BlockCommandComment_getArgText")
25 | internal let clang_BlockCommandComment_getParagraph: @convention(c) (CXComment) -> (CXComment) = library.load(symbol: "clang_BlockCommandComment_getParagraph")
26 | internal let clang_ParamCommandComment_getParamName: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_ParamCommandComment_getParamName")
27 | internal let clang_ParamCommandComment_isParamIndexValid: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_ParamCommandComment_isParamIndexValid")
28 | internal let clang_ParamCommandComment_getParamIndex: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_ParamCommandComment_getParamIndex")
29 | internal let clang_ParamCommandComment_isDirectionExplicit: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_ParamCommandComment_isDirectionExplicit")
30 | internal let clang_ParamCommandComment_getDirection: @convention(c) (CXComment) -> (CXCommentParamPassDirection) = library.load(symbol: "clang_ParamCommandComment_getDirection")
31 | internal let clang_TParamCommandComment_getParamName: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_TParamCommandComment_getParamName")
32 | internal let clang_TParamCommandComment_isParamPositionValid: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_TParamCommandComment_isParamPositionValid")
33 | internal let clang_TParamCommandComment_getDepth: @convention(c) (CXComment) -> (UInt32) = library.load(symbol: "clang_TParamCommandComment_getDepth")
34 | internal let clang_TParamCommandComment_getIndex: @convention(c) (CXComment, UInt32) -> (UInt32) = library.load(symbol: "clang_TParamCommandComment_getIndex")
35 | internal let clang_VerbatimBlockLineComment_getText: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_VerbatimBlockLineComment_getText")
36 | internal let clang_VerbatimLineComment_getText: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_VerbatimLineComment_getText")
37 | internal let clang_HTMLTagComment_getAsString: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_HTMLTagComment_getAsString")
38 | internal let clang_FullComment_getAsHTML: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_FullComment_getAsHTML")
39 | internal let clang_FullComment_getAsXML: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_FullComment_getAsXML")
40 | #endif
41 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer-IBAnalyzerTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer-IBAnalyzerTests/Pods-IBAnalyzer-IBAnalyzerTests-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## SWXMLHash
5 |
6 | Copyright (c) 2014 David Mohundro
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining
9 | a copy of this software and associated documentation files (the
10 | "Software"), to deal in the Software without restriction, including
11 | without limitation the rights to use, copy, modify, merge, publish,
12 | distribute, sublicense, and/or sell copies of the Software, and to
13 | permit persons to whom the Software is furnished to do so, subject to
14 | the following 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 OF
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 |
28 | ## SourceKittenFramework
29 |
30 | The MIT License (MIT)
31 |
32 | Copyright (c) 2014 JP Simard.
33 |
34 | Permission is hereby granted, free of charge, to any person obtaining a copy
35 | of this software and associated documentation files (the "Software"), to deal
36 | in the Software without restriction, including without limitation the rights
37 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38 | copies of the Software, and to permit persons to whom the Software is
39 | furnished to do so, subject to the following conditions:
40 |
41 | The above copyright notice and this permission notice shall be included in all
42 | copies or substantial portions of the Software.
43 |
44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50 | SOFTWARE.
51 |
52 |
53 | ## SwiftLint
54 |
55 | The MIT License (MIT)
56 |
57 | Copyright (c) 2015 Realm Inc.
58 |
59 | Permission is hereby granted, free of charge, to any person obtaining a copy
60 | of this software and associated documentation files (the "Software"), to deal
61 | in the Software without restriction, including without limitation the rights
62 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63 | copies of the Software, and to permit persons to whom the Software is
64 | furnished to do so, subject to the following conditions:
65 |
66 | The above copyright notice and this permission notice shall be included in all
67 | copies or substantial portions of the Software.
68 |
69 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
75 | SOFTWARE.
76 |
77 |
78 | ## Yams
79 |
80 | The MIT License (MIT)
81 |
82 | Copyright (c) 2016 JP Simard.
83 |
84 | Permission is hereby granted, free of charge, to any person obtaining a copy
85 | of this software and associated documentation files (the "Software"), to deal
86 | in the Software without restriction, including without limitation the rights
87 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88 | copies of the Software, and to permit persons to whom the Software is
89 | furnished to do so, subject to the following conditions:
90 |
91 | The above copyright notice and this permission notice shall be included in all
92 | copies or substantial portions of the Software.
93 |
94 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
95 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
96 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
97 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
98 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
99 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
100 | SOFTWARE.
101 |
102 | Generated by CocoaPods - https://cocoapods.org
103 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer-IBAnalyzerTests/Pods-IBAnalyzer-IBAnalyzerTests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_IBAnalyzer_IBAnalyzerTests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_IBAnalyzer_IBAnalyzerTests
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer-IBAnalyzerTests/Pods-IBAnalyzer-IBAnalyzerTests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_IBAnalyzer_IBAnalyzerTestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_IBAnalyzer_IBAnalyzerTestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer-IBAnalyzerTests/Pods-IBAnalyzer-IBAnalyzerTests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CODE_SIGN_IDENTITY =
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash" "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Yams"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks'
6 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash/SWXMLHash.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework/SourceKittenFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Yams/Yams.framework/Headers"
7 | OTHER_LDFLAGS = $(inherited) -framework "SWXMLHash" -framework "SourceKittenFramework" -framework "Yams"
8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer-IBAnalyzerTests/Pods-IBAnalyzer-IBAnalyzerTests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_IBAnalyzer_IBAnalyzerTests {
2 | umbrella header "Pods-IBAnalyzer-IBAnalyzerTests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer-IBAnalyzerTests/Pods-IBAnalyzer-IBAnalyzerTests.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CODE_SIGN_IDENTITY =
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash" "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Yams"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks'
6 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash/SWXMLHash.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework/SourceKittenFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Yams/Yams.framework/Headers"
7 | OTHER_LDFLAGS = $(inherited) -framework "SWXMLHash" -framework "SourceKittenFramework" -framework "Yams"
8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer/Pods-IBAnalyzer-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## SWXMLHash
5 |
6 | Copyright (c) 2014 David Mohundro
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining
9 | a copy of this software and associated documentation files (the
10 | "Software"), to deal in the Software without restriction, including
11 | without limitation the rights to use, copy, modify, merge, publish,
12 | distribute, sublicense, and/or sell copies of the Software, and to
13 | permit persons to whom the Software is furnished to do so, subject to
14 | the following 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 OF
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 |
28 | ## SourceKittenFramework
29 |
30 | The MIT License (MIT)
31 |
32 | Copyright (c) 2014 JP Simard.
33 |
34 | Permission is hereby granted, free of charge, to any person obtaining a copy
35 | of this software and associated documentation files (the "Software"), to deal
36 | in the Software without restriction, including without limitation the rights
37 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38 | copies of the Software, and to permit persons to whom the Software is
39 | furnished to do so, subject to the following conditions:
40 |
41 | The above copyright notice and this permission notice shall be included in all
42 | copies or substantial portions of the Software.
43 |
44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50 | SOFTWARE.
51 |
52 |
53 | ## SwiftLint
54 |
55 | The MIT License (MIT)
56 |
57 | Copyright (c) 2015 Realm Inc.
58 |
59 | Permission is hereby granted, free of charge, to any person obtaining a copy
60 | of this software and associated documentation files (the "Software"), to deal
61 | in the Software without restriction, including without limitation the rights
62 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63 | copies of the Software, and to permit persons to whom the Software is
64 | furnished to do so, subject to the following conditions:
65 |
66 | The above copyright notice and this permission notice shall be included in all
67 | copies or substantial portions of the Software.
68 |
69 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
75 | SOFTWARE.
76 |
77 |
78 | ## Yams
79 |
80 | The MIT License (MIT)
81 |
82 | Copyright (c) 2016 JP Simard.
83 |
84 | Permission is hereby granted, free of charge, to any person obtaining a copy
85 | of this software and associated documentation files (the "Software"), to deal
86 | in the Software without restriction, including without limitation the rights
87 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88 | copies of the Software, and to permit persons to whom the Software is
89 | furnished to do so, subject to the following conditions:
90 |
91 | The above copyright notice and this permission notice shall be included in all
92 | copies or substantial portions of the Software.
93 |
94 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
95 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
96 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
97 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
98 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
99 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
100 | SOFTWARE.
101 |
102 | Generated by CocoaPods - https://cocoapods.org
103 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer/Pods-IBAnalyzer-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_IBAnalyzer : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_IBAnalyzer
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer/Pods-IBAnalyzer-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_IBAnalyzerVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_IBAnalyzerVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer/Pods-IBAnalyzer.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CODE_SIGN_IDENTITY =
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash" "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Yams"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks'
6 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash/SWXMLHash.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework/SourceKittenFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Yams/Yams.framework/Headers"
7 | OTHER_LDFLAGS = $(inherited) -framework "SWXMLHash" -framework "SourceKittenFramework" -framework "Yams"
8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer/Pods-IBAnalyzer.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_IBAnalyzer {
2 | umbrella header "Pods-IBAnalyzer-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-IBAnalyzer/Pods-IBAnalyzer.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CODE_SIGN_IDENTITY =
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash" "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Yams"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks'
6 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash/SWXMLHash.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework/SourceKittenFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Yams/Yams.framework/Headers"
7 | OTHER_LDFLAGS = $(inherited) -framework "SWXMLHash" -framework "SourceKittenFramework" -framework "Yams"
8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SWXMLHash/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 4.5.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SWXMLHash/SWXMLHash-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_SWXMLHash : NSObject
3 | @end
4 | @implementation PodsDummy_SWXMLHash
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SWXMLHash/SWXMLHash-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SWXMLHash/SWXMLHash-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double SWXMLHashVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char SWXMLHashVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SWXMLHash/SWXMLHash.modulemap:
--------------------------------------------------------------------------------
1 | framework module SWXMLHash {
2 | umbrella header "SWXMLHash-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SWXMLHash/SWXMLHash.xcconfig:
--------------------------------------------------------------------------------
1 | APPLICATION_EXTENSION_API_ONLY = YES
2 | CODE_SIGN_IDENTITY =
3 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}
9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SWXMLHash
10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
11 | SKIP_INSTALL = YES
12 | SWIFT_VERSION = 3.0
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SourceKittenFramework/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 0.19.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SourceKittenFramework/SourceKittenFramework-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_SourceKittenFramework : NSObject
3 | @end
4 | @implementation PodsDummy_SourceKittenFramework
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SourceKittenFramework/SourceKittenFramework-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SourceKittenFramework/SourceKittenFramework-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "BuildSystem.h"
14 | #import "CXCompilationDatabase.h"
15 | #import "CXErrorCode.h"
16 | #import "CXString.h"
17 | #import "Documentation.h"
18 | #import "Index.h"
19 | #import "Platform.h"
20 | #import "sourcekitd.h"
21 |
22 | FOUNDATION_EXPORT double SourceKittenFrameworkVersionNumber;
23 | FOUNDATION_EXPORT const unsigned char SourceKittenFrameworkVersionString[];
24 |
25 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SourceKittenFramework/SourceKittenFramework.modulemap:
--------------------------------------------------------------------------------
1 | framework module SourceKittenFramework {
2 | umbrella header "SourceKittenFramework-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SourceKittenFramework/SourceKittenFramework.xcconfig:
--------------------------------------------------------------------------------
1 | APPLICATION_EXTENSION_API_ONLY = YES
2 | CODE_SIGN_IDENTITY =
3 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SourceKittenFramework
4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SWXMLHash" "${PODS_CONFIGURATION_BUILD_DIR}/Yams"
5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
7 | PODS_BUILD_DIR = ${BUILD_DIR}
8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
9 | PODS_ROOT = ${SRCROOT}
10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SourceKittenFramework
11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
12 | SKIP_INSTALL = YES
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Yams/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 0.5.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Yams/Yams-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Yams : NSObject
3 | @end
4 | @implementation PodsDummy_Yams
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Yams/Yams-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Yams/Yams-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "CYaml.h"
14 | #import "yaml.h"
15 | #import "yaml_private.h"
16 | #import "Yams.h"
17 |
18 | FOUNDATION_EXPORT double YamsVersionNumber;
19 | FOUNDATION_EXPORT const unsigned char YamsVersionString[];
20 |
21 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Yams/Yams.modulemap:
--------------------------------------------------------------------------------
1 | framework module Yams {
2 | umbrella header "Yams-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Yams/Yams.xcconfig:
--------------------------------------------------------------------------------
1 | APPLICATION_EXTENSION_API_ONLY = YES
2 | CODE_SIGN_IDENTITY =
3 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Yams
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}
9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Yams
10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
11 | SKIP_INSTALL = YES
12 |
--------------------------------------------------------------------------------
/Pods/Yams/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 JP Simard.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Pods/Yams/README.md:
--------------------------------------------------------------------------------
1 | # Yams
2 |
3 | 
4 |
5 | A sweet and swifty [Yaml](http://yaml.org/) parser built on
6 | [libYAML](http://pyyaml.org/wiki/LibYAML).
7 |
8 | [](https://circleci.com/gh/jpsim/Yams)
9 |
10 | ## Installation
11 |
12 | Building Yams on macOS requires Xcode 9.x or a Swift 3.2/4.x toolchain with
13 | the Swift Package Manager.
14 |
15 | Building Yams on Linux requires a Swift 4.x compiler and Swift Package Manager
16 | to be installed.
17 |
18 | ### Swift Package Manager
19 |
20 | Add `.package(url: "https://github.com/jpsim/Yams.git", from: "0.5.0")` to your
21 | `Package.swift` file's `dependencies`.
22 |
23 | ### CocoaPods
24 |
25 | Add `pod 'Yams'` to your `Podfile`.
26 |
27 | ### Carthage
28 |
29 | Add `github "jpsim/Yams"` to your `Cartfile`.
30 |
31 | ## License
32 |
33 | Both Yams and libYAML are MIT licensed.
34 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/CYaml/include/CYaml.h:
--------------------------------------------------------------------------------
1 | #include "yaml.h"
2 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/CYaml/src/writer.c:
--------------------------------------------------------------------------------
1 |
2 | #include "yaml_private.h"
3 |
4 | /*
5 | * Declarations.
6 | */
7 |
8 | static int
9 | yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem);
10 |
11 | YAML_DECLARE(int)
12 | yaml_emitter_flush(yaml_emitter_t *emitter);
13 |
14 | /*
15 | * Set the writer error and return 0.
16 | */
17 |
18 | static int
19 | yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
20 | {
21 | emitter->error = YAML_WRITER_ERROR;
22 | emitter->problem = problem;
23 |
24 | return 0;
25 | }
26 |
27 | /*
28 | * Flush the output buffer.
29 | */
30 |
31 | YAML_DECLARE(int)
32 | yaml_emitter_flush(yaml_emitter_t *emitter)
33 | {
34 | int low, high;
35 |
36 | assert(emitter); /* Non-NULL emitter object is expected. */
37 | assert(emitter->write_handler); /* Write handler must be set. */
38 | assert(emitter->encoding); /* Output encoding must be set. */
39 |
40 | emitter->buffer.last = emitter->buffer.pointer;
41 | emitter->buffer.pointer = emitter->buffer.start;
42 |
43 | /* Check if the buffer is empty. */
44 |
45 | if (emitter->buffer.start == emitter->buffer.last) {
46 | return 1;
47 | }
48 |
49 | /* If the output encoding is UTF-8, we don't need to recode the buffer. */
50 |
51 | if (emitter->encoding == YAML_UTF8_ENCODING)
52 | {
53 | if (emitter->write_handler(emitter->write_handler_data,
54 | emitter->buffer.start,
55 | emitter->buffer.last - emitter->buffer.start)) {
56 | emitter->buffer.last = emitter->buffer.start;
57 | emitter->buffer.pointer = emitter->buffer.start;
58 | return 1;
59 | }
60 | else {
61 | return yaml_emitter_set_writer_error(emitter, "write error");
62 | }
63 | }
64 |
65 | /* Recode the buffer into the raw buffer. */
66 |
67 | low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
68 | high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
69 |
70 | while (emitter->buffer.pointer != emitter->buffer.last)
71 | {
72 | unsigned char octet;
73 | unsigned int width;
74 | unsigned int value;
75 | size_t k;
76 |
77 | /*
78 | * See the "reader.c" code for more details on UTF-8 encoding. Note
79 | * that we assume that the buffer contains a valid UTF-8 sequence.
80 | */
81 |
82 | /* Read the next UTF-8 character. */
83 |
84 | octet = emitter->buffer.pointer[0];
85 |
86 | width = (octet & 0x80) == 0x00 ? 1 :
87 | (octet & 0xE0) == 0xC0 ? 2 :
88 | (octet & 0xF0) == 0xE0 ? 3 :
89 | (octet & 0xF8) == 0xF0 ? 4 : 0;
90 |
91 | value = (octet & 0x80) == 0x00 ? octet & 0x7F :
92 | (octet & 0xE0) == 0xC0 ? octet & 0x1F :
93 | (octet & 0xF0) == 0xE0 ? octet & 0x0F :
94 | (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
95 |
96 | for (k = 1; k < width; k ++) {
97 | octet = emitter->buffer.pointer[k];
98 | value = (value << 6) + (octet & 0x3F);
99 | }
100 |
101 | emitter->buffer.pointer += width;
102 |
103 | /* Write the character. */
104 |
105 | if (value < 0x10000)
106 | {
107 | emitter->raw_buffer.last[high] = value >> 8;
108 | emitter->raw_buffer.last[low] = value & 0xFF;
109 |
110 | emitter->raw_buffer.last += 2;
111 | }
112 | else
113 | {
114 | /* Write the character using a surrogate pair (check "reader.c"). */
115 |
116 | value -= 0x10000;
117 | emitter->raw_buffer.last[high] = 0xD8 + (value >> 18);
118 | emitter->raw_buffer.last[low] = (value >> 10) & 0xFF;
119 | emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF);
120 | emitter->raw_buffer.last[low+2] = value & 0xFF;
121 |
122 | emitter->raw_buffer.last += 4;
123 | }
124 | }
125 |
126 | /* Write the raw buffer. */
127 |
128 | if (emitter->write_handler(emitter->write_handler_data,
129 | emitter->raw_buffer.start,
130 | emitter->raw_buffer.last - emitter->raw_buffer.start)) {
131 | emitter->buffer.last = emitter->buffer.start;
132 | emitter->buffer.pointer = emitter->buffer.start;
133 | emitter->raw_buffer.last = emitter->raw_buffer.start;
134 | emitter->raw_buffer.pointer = emitter->raw_buffer.start;
135 | return 1;
136 | }
137 | else {
138 | return yaml_emitter_set_writer_error(emitter, "write error");
139 | }
140 | }
141 |
142 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/Mark.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Mark.swift
3 | // Yams
4 | //
5 | // Created by Norio Nomura on 4/11/17.
6 | // Copyright (c) 2017 Yams. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct Mark {
12 | /// line start from 1
13 | public let line: Int
14 | /// column start from 1. libYAML counts column by unicodeScalars.
15 | public let column: Int
16 | }
17 |
18 | extension Mark: CustomStringConvertible {
19 | public var description: String { return "\(line):\(column)" }
20 | }
21 |
22 | extension Mark {
23 | public func snippet(from yaml: String) -> String {
24 | let contents = yaml.substring(at: line - 1)
25 | let columnIndex = contents.unicodeScalars
26 | .index(contents.unicodeScalars.startIndex,
27 | offsetBy: column - 1,
28 | limitedBy: contents.unicodeScalars.endIndex)?
29 | .samePosition(in: contents.utf16) ?? contents.utf16.endIndex
30 | let columnInUTF16 = contents.utf16.distance(from: contents.utf16.startIndex, to: columnIndex)
31 | return contents.endingWithNewLine +
32 | String(repeating: " ", count: columnInUTF16) + "^"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/Node.Mapping.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Node.Mapping.swift
3 | // Yams
4 | //
5 | // Created by Norio Nomura on 2/24/17.
6 | // Copyright (c) 2016 Yams. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Node {
12 | public struct Mapping {
13 | fileprivate var pairs: [Pair]
14 | public var tag: Tag
15 | public var style: Style
16 | public var mark: Mark?
17 |
18 | public enum Style: UInt32 { // swiftlint:disable:this nesting
19 | /// Let the emitter choose the style.
20 | case any
21 | /// The block mapping style.
22 | case block
23 | /// The flow mapping style.
24 | case flow
25 | }
26 |
27 | public init(_ pairs: [(Node, Node)], _ tag: Tag = .implicit, _ style: Style = .any, _ mark: Mark? = nil) {
28 | self.pairs = pairs.map { Pair($0.0, $0.1) }
29 | self.tag = tag
30 | self.style = style
31 | self.mark = mark
32 | }
33 | }
34 |
35 | public var mapping: Mapping? {
36 | get {
37 | if case let .mapping(mapping) = self {
38 | return mapping
39 | }
40 | return nil
41 | }
42 | set {
43 | if let newValue = newValue {
44 | self = .mapping(newValue)
45 | }
46 | }
47 | }
48 | }
49 |
50 | extension Node.Mapping: Comparable {
51 | public static func < (lhs: Node.Mapping, rhs: Node.Mapping) -> Bool {
52 | return lhs.pairs < rhs.pairs
53 | }
54 | }
55 |
56 | extension Node.Mapping: Equatable {
57 | public static func == (lhs: Node.Mapping, rhs: Node.Mapping) -> Bool {
58 | return lhs.pairs == rhs.pairs && lhs.resolvedTag == rhs.resolvedTag
59 | }
60 | }
61 |
62 | extension Node.Mapping: ExpressibleByDictionaryLiteral {
63 | public init(dictionaryLiteral elements: (Node, Node)...) {
64 | self.init(elements)
65 | }
66 | }
67 |
68 | extension Node.Mapping: MutableCollection {
69 | public typealias Element = (key: Node, value: Node)
70 |
71 | // Sequence
72 | public func makeIterator() -> Array.Iterator {
73 | let iterator = pairs.map(Pair.toTuple).makeIterator()
74 | return iterator
75 | }
76 |
77 | // Collection
78 | public typealias Index = Array.Index
79 |
80 | public var startIndex: Int {
81 | return pairs.startIndex
82 | }
83 |
84 | public var endIndex: Int {
85 | return pairs.endIndex
86 | }
87 |
88 | public func index(after index: Int) -> Int {
89 | return pairs.index(after: index)
90 | }
91 |
92 | public subscript(index: Int) -> Element {
93 | get {
94 | return (key: pairs[index].key, value: pairs[index].value)
95 | }
96 | // MutableCollection
97 | set {
98 | pairs[index] = Pair(newValue.key, newValue.value)
99 | }
100 | }
101 | }
102 |
103 | extension Node.Mapping: TagResolvable {
104 | static let defaultTagName = Tag.Name.map
105 | }
106 |
107 | extension Node.Mapping {
108 | public var keys: LazyMapCollection {
109 | return lazy.map { $0.key }
110 | }
111 |
112 | public var values: LazyMapCollection {
113 | return lazy.map { $0.value }
114 | }
115 |
116 | public subscript(string: String) -> Node? {
117 | get {
118 | return self[Node(string)]
119 | }
120 | set {
121 | self[Node(string)] = newValue
122 | }
123 | }
124 |
125 | public subscript(node: Node) -> Node? {
126 | get {
127 | let v = pairs.reversed().first(where: { $0.key == node })
128 | return v?.value
129 | }
130 | set {
131 | if let newValue = newValue {
132 | if let index = index(forKey: node) {
133 | pairs[index] = Pair(pairs[index].key, newValue)
134 | } else {
135 | pairs.append(Pair(node, newValue))
136 | }
137 | } else {
138 | if let index = index(forKey: node) {
139 | pairs.remove(at: index)
140 | }
141 | }
142 | }
143 | }
144 |
145 | public func index(forKey key: Node) -> Int? {
146 | return pairs.reversed().index(where: { $0.key == key }).map({ pairs.index(before: $0.base) })
147 | }
148 | }
149 |
150 | private struct Pair: Comparable, Equatable {
151 | let key: Value
152 | let value: Value
153 |
154 | init(_ key: Value, _ value: Value) {
155 | self.key = key
156 | self.value = value
157 | }
158 |
159 | static func == (lhs: Pair, rhs: Pair) -> Bool {
160 | return lhs.key == rhs.key && lhs.value == rhs.value
161 | }
162 |
163 | static func < (lhs: Pair, rhs: Pair) -> Bool {
164 | return lhs.key < rhs.key
165 | }
166 |
167 | static func toTuple(pair: Pair) -> (key: Value, value: Value) {
168 | return (key: pair.key, value: pair.value)
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/Node.Scalar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Node.Scalar.swift
3 | // Yams
4 | //
5 | // Created by Norio Nomura on 2/24/17.
6 | // Copyright (c) 2016 Yams. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Node {
12 | public struct Scalar {
13 | public var string: String {
14 | didSet {
15 | tag = .implicit
16 | }
17 | }
18 | public var tag: Tag
19 | public var style: Style
20 | public var mark: Mark?
21 |
22 | public enum Style: UInt32 { // swiftlint:disable:this nesting
23 | /// Let the emitter choose the style.
24 | case any = 0
25 | /// The plain scalar style.
26 | case plain
27 |
28 | /// The single-quoted scalar style.
29 | case singleQuoted
30 | /// The double-quoted scalar style.
31 | case doubleQuoted
32 |
33 | /// The literal scalar style.
34 | case literal
35 | /// The folded scalar style.
36 | case folded
37 | }
38 |
39 | public init(_ string: String, _ tag: Tag = .implicit, _ style: Style = .any, _ mark: Mark? = nil) {
40 | self.string = string
41 | self.tag = tag
42 | self.style = style
43 | self.mark = mark
44 | }
45 | }
46 |
47 | public var scalar: Scalar? {
48 | get {
49 | if case let .scalar(scalar) = self {
50 | return scalar
51 | }
52 | return nil
53 | }
54 | set {
55 | if let newValue = newValue {
56 | self = .scalar(newValue)
57 | }
58 | }
59 | }
60 | }
61 |
62 | extension Node.Scalar: Comparable {
63 | public static func < (lhs: Node.Scalar, rhs: Node.Scalar) -> Bool {
64 | return lhs.string < rhs.string
65 | }
66 | }
67 |
68 | extension Node.Scalar: Equatable {
69 | public static func == (lhs: Node.Scalar, rhs: Node.Scalar) -> Bool {
70 | return lhs.string == rhs.string && lhs.resolvedTag == rhs.resolvedTag
71 | }
72 | }
73 |
74 | extension Node.Scalar: TagResolvable {
75 | static let defaultTagName = Tag.Name.str
76 | func resolveTag(using resolver: Resolver) -> Tag.Name {
77 | return tag.name == .implicit ? resolver.resolveTag(from: string) : tag.name
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/Node.Sequence.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Node.Sequence.swift
3 | // Yams
4 | //
5 | // Created by Norio Nomura on 2/24/17.
6 | // Copyright (c) 2016 Yams. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Node {
12 | public struct Sequence {
13 | fileprivate var nodes: [Node]
14 | public var tag: Tag
15 | public var style: Style
16 | public var mark: Mark?
17 |
18 | public enum Style: UInt32 { // swiftlint:disable:this nesting
19 | /// Let the emitter choose the style.
20 | case any
21 | /// The block sequence style.
22 | case block
23 | /// The flow sequence style.
24 | case flow
25 | }
26 |
27 | public init(_ nodes: [Node], _ tag: Tag = .implicit, _ style: Style = .any, _ mark: Mark? = nil) {
28 | self.nodes = nodes
29 | self.tag = tag
30 | self.style = style
31 | self.mark = mark
32 | }
33 | }
34 |
35 | public var sequence: Sequence? {
36 | get {
37 | if case let .sequence(sequence) = self {
38 | return sequence
39 | }
40 | return nil
41 | }
42 | set {
43 | if let newValue = newValue {
44 | self = .sequence(newValue)
45 | }
46 | }
47 | }
48 | }
49 |
50 | // MARK: - Node.Sequence
51 |
52 | extension Node.Sequence: Comparable {
53 | public static func < (lhs: Node.Sequence, rhs: Node.Sequence) -> Bool {
54 | return lhs.nodes < rhs.nodes
55 | }
56 | }
57 |
58 | extension Node.Sequence: Equatable {
59 | public static func == (lhs: Node.Sequence, rhs: Node.Sequence) -> Bool {
60 | return lhs.nodes == rhs.nodes && lhs.resolvedTag == rhs.resolvedTag
61 | }
62 | }
63 |
64 | extension Node.Sequence: ExpressibleByArrayLiteral {
65 | public init(arrayLiteral elements: Node...) {
66 | self.init(elements)
67 | }
68 | }
69 |
70 | extension Node.Sequence: MutableCollection {
71 | // Sequence
72 | public func makeIterator() -> Array.Iterator {
73 | return nodes.makeIterator()
74 | }
75 |
76 | // Collection
77 | public typealias Index = Array.Index
78 |
79 | public var startIndex: Index {
80 | return nodes.startIndex
81 | }
82 |
83 | public var endIndex: Index {
84 | return nodes.endIndex
85 | }
86 |
87 | public func index(after index: Index) -> Index {
88 | return nodes.index(after: index)
89 | }
90 |
91 | public subscript(index: Index) -> Node {
92 | get {
93 | return nodes[index]
94 | }
95 | // MutableCollection
96 | set {
97 | nodes[index] = newValue
98 | }
99 | }
100 |
101 | public subscript(bounds: Range) -> Array.SubSequence {
102 | get {
103 | return nodes[bounds]
104 | }
105 | // MutableCollection
106 | set {
107 | nodes[bounds] = newValue
108 | }
109 | }
110 |
111 | public var indices: Array.Indices {
112 | return nodes.indices
113 | }
114 | }
115 |
116 | extension Node.Sequence: RandomAccessCollection {
117 | // BidirectionalCollection
118 | public func index(before index: Index) -> Index {
119 | return nodes.index(before: index)
120 | }
121 |
122 | // RandomAccessCollection
123 | public func index(_ index: Index, offsetBy num: Int) -> Index {
124 | return nodes.index(index, offsetBy: num)
125 | }
126 |
127 | public func distance(from start: Index, to end: Int) -> Index {
128 | return nodes.distance(from: start, to: end)
129 | }
130 | }
131 |
132 | extension Node.Sequence: RangeReplaceableCollection {
133 | public init() {
134 | self.init([])
135 | }
136 |
137 | public mutating func replaceSubrange(_ subrange: Range, with newElements: C)
138 | where C: Collection, C.Iterator.Element == Node {
139 | nodes.replaceSubrange(subrange, with: newElements)
140 | }
141 | }
142 |
143 | extension Node.Sequence: TagResolvable {
144 | static let defaultTagName = Tag.Name.seq
145 | }
146 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/Resolver.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Resolver.swift
3 | // Yams
4 | //
5 | // Created by Norio Nomura on 12/15/16.
6 | // Copyright (c) 2016 Yams. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public final class Resolver {
12 | public struct Rule {
13 | public let tag: Tag.Name
14 | let regexp: NSRegularExpression
15 | public var pattern: String { return regexp.pattern }
16 |
17 | public init(_ tag: Tag.Name, _ pattern: String) throws {
18 | self.tag = tag
19 | self.regexp = try .init(pattern: pattern, options: [])
20 | }
21 | }
22 |
23 | public let rules: [Rule]
24 |
25 | init(_ rules: [Rule] = []) { self.rules = rules }
26 |
27 | public func resolveTag(of node: Node) -> Tag.Name {
28 | switch node {
29 | case let .scalar(scalar):
30 | return resolveTag(of: scalar)
31 | case let .mapping(mapping):
32 | return resolveTag(of: mapping)
33 | case let .sequence(sequence):
34 | return resolveTag(of: sequence)
35 | }
36 | }
37 |
38 | /// Returns a Resolver constructed by appending rule.
39 | public func appending(_ rule: Rule) -> Resolver {
40 | return .init(rules + [rule])
41 | }
42 |
43 | /// Returns a Resolver constructed by appending pattern for tag.
44 | public func appending(_ tag: Tag.Name, _ pattern: String) throws -> Resolver {
45 | return appending(try Rule(tag, pattern))
46 | }
47 |
48 | /// Returns a Resolver constructed by replacing rule.
49 | public func replacing(_ rule: Rule) -> Resolver {
50 | return .init(rules.map { $0.tag == rule.tag ? rule : $0 })
51 | }
52 |
53 | /// Returns a Resolver constructed by replacing pattern for tag.
54 | public func replacing(_ tag: Tag.Name, with pattern: String) throws -> Resolver {
55 | return .init(try rules.map { $0.tag == tag ? try Rule($0.tag, pattern) : $0 })
56 | }
57 |
58 | /// Returns a Resolver constructed by removing pattern for tag.
59 | public func removing(_ tag: Tag.Name) -> Resolver {
60 | return .init(rules.filter({ $0.tag != tag }))
61 | }
62 |
63 | // MARK: - internal
64 |
65 | func resolveTag(of value: T) -> Tag.Name where T: TagResolvable {
66 | return value.resolveTag(using: self)
67 | }
68 |
69 | func resolveTag(from string: String) -> Tag.Name {
70 | for rule in rules where rule.regexp.matches(in: string) {
71 | return rule.tag
72 | }
73 | return .str
74 | }
75 | }
76 |
77 | extension Resolver {
78 | public static let basic = Resolver()
79 | public static let `default` = Resolver([.bool, .int, .float, .merge, .null, .timestamp, .value])
80 | }
81 |
82 | extension Resolver.Rule {
83 | // swiftlint:disable:next force_try
84 | public static let bool = try! Resolver.Rule(.bool, """
85 | ^(?:yes|Yes|YES|no|No|NO\
86 | |true|True|TRUE|false|False|FALSE\
87 | |on|On|ON|off|Off|OFF)$
88 | """)
89 | // swiftlint:disable:next force_try
90 | public static let int = try! Resolver.Rule(.int, """
91 | ^(?:[-+]?0b[0-1_]+\
92 | |[-+]?0o?[0-7_]+\
93 | |[-+]?(?:0|[1-9][0-9_]*)\
94 | |[-+]?0x[0-9a-fA-F_]+\
95 | |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$
96 | """)
97 | // swiftlint:disable:next force_try
98 | public static let float = try! Resolver.Rule(.float, """
99 | ^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?\
100 | |\\.[0-9_]+(?:[eE][-+][0-9]+)?\
101 | |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\
102 | |[-+]?\\.(?:inf|Inf|INF)\
103 | |\\.(?:nan|NaN|NAN))$
104 | """)
105 | // swiftlint:disable:next force_try
106 | public static let merge = try! Resolver.Rule(.merge, "^(?:<<)$")
107 | // swiftlint:disable:next force_try
108 | public static let null = try! Resolver.Rule(.null, """
109 | ^(?:~\
110 | |null|Null|NULL\
111 | |)$
112 | """)
113 | // swiftlint:disable:next force_try
114 | public static let timestamp = try! Resolver.Rule(.timestamp, """
115 | ^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\
116 | |[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?\
117 | (?:[Tt]|[ \\t]+)[0-9][0-9]?\
118 | :[0-9][0-9]:[0-9][0-9](?:\\.[0-9]*)?\
119 | (?:[ \\t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$
120 | """)
121 | // swiftlint:disable:next force_try
122 | public static let value = try! Resolver.Rule(.value, "^(?:=)$")
123 | }
124 |
125 | func pattern(_ string: String) -> NSRegularExpression {
126 | do {
127 | return try .init(pattern: string, options: [])
128 | } catch {
129 | fatalError("unreachable")
130 | }
131 | }
132 |
133 | extension NSRegularExpression {
134 | fileprivate func matches(in string: String) -> Bool {
135 | let range = NSRange(location: 0, length: string.utf16.count)
136 | if let match = firstMatch(in: string, options: [], range: range) {
137 | return match.range.location != NSNotFound
138 | }
139 | return false
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/String+Yams.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+Yams.swift
3 | // Yams
4 | //
5 | // Created by Norio Nomura on 12/7/16.
6 | // Copyright (c) 2016 Yams. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension String {
12 | typealias LineNumberColumnAndContents = (lineNumber: Int, column: Int, contents: String)
13 |
14 | /// line number, column and contents at utf8 offset.
15 | ///
16 | /// - Parameter offset: Int
17 | /// - Returns: lineNumber: line number start from 0,
18 | /// column: utf16 column start from 0,
19 | /// contents: substring of line
20 | func utf8LineNumberColumnAndContents(at offset: Int) -> LineNumberColumnAndContents? {
21 | guard let index = utf8
22 | .index(utf8.startIndex, offsetBy: offset, limitedBy: utf8.endIndex)?
23 | .samePosition(in: self) else { return nil }
24 | return lineNumberColumnAndContents(at: index)
25 | }
26 |
27 | /// line number, column and contents at utf16 offset.
28 | ///
29 | /// - Parameter offset: Int
30 | /// - Returns: lineNumber: line number start from 0,
31 | /// column: utf16 column start from 0,
32 | /// contents: substring of line
33 | func utf16LineNumberColumnAndContents(at offset: Int) -> LineNumberColumnAndContents? {
34 | guard let index = utf16
35 | .index(utf16.startIndex, offsetBy: offset, limitedBy: utf16.endIndex)?
36 | .samePosition(in: self) else { return nil }
37 | return lineNumberColumnAndContents(at: index)
38 | }
39 |
40 | /// line number, column and contents at Index.
41 | ///
42 | /// - Parameter index: String.Index
43 | /// - Returns: lineNumber: line number start from 0,
44 | /// column: utf16 column start from 0,
45 | /// contents: substring of line
46 | func lineNumberColumnAndContents(at index: Index) -> LineNumberColumnAndContents {
47 | assert((startIndex.. String {
72 | var number = 0
73 | var outStartIndex = startIndex, outEndIndex = startIndex, outContentsEndIndex = startIndex
74 | getLineStart(&outStartIndex, end: &outEndIndex, contentsEnd: &outContentsEndIndex,
75 | for: startIndex..(with value: T) -> Tag where T: TagResolvable {
39 | if name == .implicit {
40 | name = resolver.resolveTag(of: value)
41 | } else if name == .nonSpecific {
42 | name = T.defaultTagName
43 | }
44 | return self
45 | }
46 |
47 | // fileprivate
48 | fileprivate let resolver: Resolver
49 | }
50 |
51 | extension Tag: CustomStringConvertible {
52 | public var description: String {
53 | return name.rawValue
54 | }
55 | }
56 |
57 | extension Tag: Hashable {
58 | public var hashValue: Int {
59 | return name.hashValue
60 | }
61 |
62 | public static func == (lhs: Tag, rhs: Tag) -> Bool {
63 | return lhs.name == rhs.name
64 | }
65 | }
66 |
67 | extension Tag.Name: ExpressibleByStringLiteral {
68 | public init(stringLiteral value: String) {
69 | self.rawValue = value
70 | }
71 |
72 | public init(unicodeScalarLiteral value: String) {
73 | self.rawValue = value
74 | }
75 |
76 | public init(extendedGraphemeClusterLiteral value: String) {
77 | self.rawValue = value
78 | }
79 | }
80 |
81 | extension Tag.Name: Hashable {
82 | public var hashValue: Int {
83 | return rawValue.hashValue
84 | }
85 |
86 | public static func == (lhs: Tag.Name, rhs: Tag.Name) -> Bool {
87 | return lhs.rawValue == rhs.rawValue
88 | }
89 | }
90 |
91 | // http://www.yaml.org/spec/1.2/spec.html#Schema
92 | extension Tag.Name {
93 | // Special
94 | /// Tag should be resolved by value.
95 | public static let implicit: Tag.Name = ""
96 | /// Tag should not be resolved by value, and be resolved as .str, .seq or .map.
97 | public static let nonSpecific: Tag.Name = "!"
98 |
99 | // Failsafe Schema
100 | /// "tag:yaml.org,2002:str"
101 | public static let str: Tag.Name = "tag:yaml.org,2002:str"
102 | /// "tag:yaml.org,2002:seq"
103 | public static let seq: Tag.Name = "tag:yaml.org,2002:seq"
104 | /// "tag:yaml.org,2002:map"
105 | public static let map: Tag.Name = "tag:yaml.org,2002:map"
106 | // JSON Schema
107 | /// "tag:yaml.org,2002:bool"
108 | public static let bool: Tag.Name = "tag:yaml.org,2002:bool"
109 | /// "tag:yaml.org,2002:float"
110 | public static let float: Tag.Name = "tag:yaml.org,2002:float"
111 | /// "tag:yaml.org,2002:null"
112 | public static let null: Tag.Name = "tag:yaml.org,2002:null"
113 | /// "tag:yaml.org,2002:int"
114 | public static let int: Tag.Name = "tag:yaml.org,2002:int"
115 | // http://yaml.org/type/index.html
116 | /// "tag:yaml.org,2002:binary"
117 | public static let binary: Tag.Name = "tag:yaml.org,2002:binary"
118 | /// "tag:yaml.org,2002:merge"
119 | public static let merge: Tag.Name = "tag:yaml.org,2002:merge"
120 | /// "tag:yaml.org,2002:omap"
121 | public static let omap: Tag.Name = "tag:yaml.org,2002:omap"
122 | /// "tag:yaml.org,2002:pairs"
123 | public static let pairs: Tag.Name = "tag:yaml.org,2002:pairs"
124 | /// "tag:yaml.org,2002:set".
125 | public static let set: Tag.Name = "tag:yaml.org,2002:set"
126 | /// "tag:yaml.org,2002:timestamp"
127 | public static let timestamp: Tag.Name = "tag:yaml.org,2002:timestamp"
128 | /// "tag:yaml.org,2002:value"
129 | public static let value: Tag.Name = "tag:yaml.org,2002:value"
130 | /// "tag:yaml.org,2002:yaml" We don't support this.
131 | public static let yaml: Tag.Name = "tag:yaml.org,2002:yaml"
132 | }
133 |
134 | protocol TagResolvable {
135 | var tag: Tag { get }
136 | static var defaultTagName: Tag.Name { get }
137 | func resolveTag(using resolver: Resolver) -> Tag.Name
138 | }
139 |
140 | extension TagResolvable {
141 | var resolvedTag: Tag {
142 | return tag.resolved(with: self)
143 | }
144 |
145 | func resolveTag(using resolver: Resolver) -> Tag.Name {
146 | return tag.name == .implicit ? Self.defaultTagName : tag.name
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/YamlError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // YamlError.swift
3 | // Yams
4 | //
5 | // Created by JP Simard on 2016-11-19.
6 | // Copyright (c) 2016 Yams. All rights reserved.
7 | //
8 |
9 | #if SWIFT_PACKAGE
10 | import CYaml
11 | #endif
12 | import Foundation
13 |
14 | public enum YamlError: Swift.Error {
15 | // Used in `yaml_emitter_t` and `yaml_parser_t`
16 | /// YAML_NO_ERROR. No error is produced.
17 | case no // swiftlint:disable:this identifier_name
18 | /// YAML_MEMORY_ERROR. Cannot allocate or reallocate a block of memory.
19 | case memory
20 |
21 | // Used in `yaml_parser_t`
22 | /// YAML_READER_ERROR. Cannot read or decode the input stream.
23 | case reader(problem: String, byteOffset: Int, value: Int32, yaml: String)
24 |
25 | // line and column start from 1, column is counted by unicodeScalars
26 | /// YAML_SCANNER_ERROR. Cannot scan the input stream.
27 | case scanner(context: Context?, problem: String, Mark, yaml: String)
28 | /// YAML_PARSER_ERROR. Cannot parse the input stream.
29 | case parser(context: Context?, problem: String, Mark, yaml: String)
30 | /// YAML_COMPOSER_ERROR. Cannot compose a YAML document.
31 | case composer(context: Context?, problem: String, Mark, yaml: String)
32 |
33 | // Used in `yaml_emitter_t`
34 | /// YAML_WRITER_ERROR. Cannot write to the output stream.
35 | case writer(problem: String)
36 | /// YAML_EMITTER_ERROR. Cannot emit a YAML stream.
37 | case emitter(problem: String)
38 |
39 | // Used in `NodeRepresentable`
40 | case representer(problem: String)
41 |
42 | public struct Context: CustomStringConvertible {
43 | public let text: String
44 | public let mark: Mark
45 | public var description: String {
46 | return text + " in line \(mark.line), column \(mark.column)\n"
47 | }
48 | }
49 | }
50 |
51 | extension YamlError {
52 | init(from parser: yaml_parser_t, with yaml: String) {
53 | func context(from parser: yaml_parser_t) -> Context? {
54 | guard let context = parser.context else { return nil }
55 | return Context(
56 | text: String(cString: context),
57 | mark: Mark(line: parser.context_mark.line + 1, column: parser.context_mark.column + 1)
58 | )
59 | }
60 |
61 | func problemMark(from parser: yaml_parser_t) -> Mark {
62 | return Mark(line: parser.problem_mark.line + 1, column: parser.problem_mark.column + 1)
63 | }
64 |
65 | switch parser.error {
66 | case YAML_MEMORY_ERROR:
67 | self = .memory
68 | case YAML_READER_ERROR:
69 | self = .reader(problem: String(cString: parser.problem),
70 | byteOffset: parser.problem_offset,
71 | value: parser.problem_value,
72 | yaml: yaml)
73 | case YAML_SCANNER_ERROR:
74 | self = .scanner(context: context(from: parser),
75 | problem: String(cString: parser.problem), problemMark(from: parser),
76 | yaml: yaml)
77 | case YAML_PARSER_ERROR:
78 | self = .parser(context: context(from: parser),
79 | problem: String(cString: parser.problem), problemMark(from: parser),
80 | yaml: yaml)
81 | case YAML_COMPOSER_ERROR:
82 | self = .composer(context: context(from: parser),
83 | problem: String(cString: parser.problem), problemMark(from: parser),
84 | yaml: yaml)
85 | default:
86 | fatalError("Parser has unknown error: \(parser.error)!")
87 | }
88 | }
89 |
90 | init(from emitter: yaml_emitter_t) {
91 | switch emitter.error {
92 | case YAML_MEMORY_ERROR:
93 | self = .memory
94 | case YAML_EMITTER_ERROR:
95 | self = .emitter(problem: String(cString: emitter.problem))
96 | default:
97 | fatalError("Emitter has unknown error: \(emitter.error)!")
98 | }
99 | }
100 | }
101 |
102 | extension YamlError: CustomStringConvertible {
103 | public var description: String {
104 | switch self {
105 | case .no:
106 | return "No error is produced"
107 | case .memory:
108 | return "Memory error"
109 | case let .reader(problem, byteOffset, value, yaml):
110 | guard let (mark, contents) = markAndSnippet(from: yaml, byteOffset)
111 | else { return "\(problem) at byte offset: \(byteOffset), value: \(value)" }
112 | return "\(mark): error: reader: \(problem):\n" + contents.endingWithNewLine
113 | + String(repeating: " ", count: mark.column - 1) + "^"
114 | case let .scanner(context, problem, mark, yaml):
115 | return "\(mark): error: scanner: \(context?.description ?? "")\(problem):\n" + mark.snippet(from: yaml)
116 | case let .parser(context, problem, mark, yaml):
117 | return "\(mark): error: parser: \(context?.description ?? "")\(problem):\n" + mark.snippet(from: yaml)
118 | case let .composer(context, problem, mark, yaml):
119 | return "\(mark): error: composer: \(context?.description ?? "")\(problem):\n" + mark.snippet(from: yaml)
120 | case let .writer(problem), let .emitter(problem), let .representer(problem):
121 | return problem
122 | }
123 | }
124 | }
125 |
126 | extension YamlError {
127 | fileprivate func markAndSnippet(from yaml: String, _ byteOffset: Int) -> (Mark, String)? {
128 | #if USE_UTF8
129 | guard let (line, column, contents) = yaml.utf8LineNumberColumnAndContents(at: byteOffset)
130 | else { return nil }
131 | #else
132 | guard let (line, column, contents) = yaml.utf16LineNumberColumnAndContents(at: byteOffset / 2)
133 | else { return nil }
134 | #endif
135 | return (Mark(line: line + 1, column: column + 1), contents)
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/Pods/Yams/Sources/Yams/Yams.h:
--------------------------------------------------------------------------------
1 | //
2 | // Yams.h
3 | // Yams
4 | //
5 | // Created by Norio Nomura on 1/25/17.
6 | // Copyright (c) 2017 Yams. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Yams.
12 | FOUNDATION_EXPORT double YamsVersionNumber;
13 |
14 | //! Project version string for Yams.
15 | FOUNDATION_EXPORT const unsigned char YamsVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 | #import
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/fastred/IBAnalyzer) [](https://codecov.io/gh/fastred/IBAnalyzer)
2 |
3 | # IBAnalyzer
4 |
5 | Find common xib and storyboard-related problems without running your app or writing unit tests.
6 |
7 | ## Usage
8 |
9 | Pass a path to your project to `ibanalyzer` command line tool. Here's an example output you can expect:
10 |
11 | ```
12 | $ ./ibanalyzer ~/code/Sample/
13 |
14 | TwitterViewController doesn't implement a required @IBAction named: loginButtonPressed:
15 | TwitterViewController doesn't implement a required @IBOutlet named: twitterImageView
16 | LoginViewController contains unused @IBAction named: onePasswordButtonTapped:
17 | MessageCell contains unused @IBOutlet named: unreadIndicatorView
18 | MessagesViewController contains unused @IBAction named: infoButtonPressed
19 | ```
20 |
21 | With IBAnalyzer, you're able to:
22 |
23 | 1. Find unimplemented outlets & actions in classes. Avoid crashes caused by exceptions, like the dreadful:
24 | ```
25 | *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '
26 | [ setValue:forUndefinedKey:]: this
27 | class is not key value coding-compliant for the key twitterImageView.'
28 | ```
29 |
30 | 2. Find `@IBOutlet`s and `@IBAction`s defined in code but not connected to from nibs. No more:
31 |
32 |
33 |
34 | and
35 |
36 |
37 |
38 | ## Drawbacks
39 |
40 | This is a new tool, used only on a handful of projects till now. If you encounter any bugs, please create new issues.
41 |
42 | **Doesn't work with Objective-C. Tested on Swift 3.0.**
43 |
44 | ## How It Works
45 |
46 | IBAnalyzer starts by parsing all `.xib,` `.storyboard` and `.swift` files in the provided folder. It then uses this data (wrapped in `AnalyzerConfiguration`) to generate warnings. You can see the source of an analyzer [checking connections between source code and nibs here](https://github.com/fastred/IBAnalyzer/blob/master/IBAnalyzer/Analyzers/ConnectionAnalyzer.swift).
47 |
48 | New warnings can be implemented by adding a new type conforming to the `Analyzer` protocol and initializing it in `main.swift`. Check [issues](https://github.com/fastred/IBAnalyzer/issues) to learn about some ideas for new warnings.
49 |
50 | ## Installation
51 |
52 | ### CocoaPods (Build Phase integration)
53 |
54 | Note: This can significantly slow-down your build times.
55 |
56 | 1. Add `pod 'IBAnalyzer'` to your `Podfile`.
57 | 1. Run `pod repo update` and then `pod install`.
58 | 1. Go to target settings -> Build Phases and add a `New Run Script Phase`. Change its name to something like `IBAnalyzer`.
59 | 1. Use this script to run analysis on all files in your repository (possibly including 3rd party dependencies, like `Pods/`):
60 |
61 | ```
62 | "${PODS_ROOT}/IBAnalyzer/bin/ibanalyzer" ./
63 | ```
64 |
65 | or this one to run analysis only on a single folder:
66 |
67 | ```
68 | "${PODS_ROOT}/IBAnalyzer/bin/ibanalyzer" FolderName/
69 | ```
70 |
71 | ### Binary
72 |
73 | Download the newest prebuilt binary from the [Releases](https://github.com/fastred/IBAnalyzer/releases) tab. Unpack and run using:
74 |
75 | ```
76 | $ bin/ibanalyzer /path/to/your/project
77 | ```
78 |
79 | ### From Source
80 |
81 | 1. Clone or download the repo.
82 | 1. Open `IBAnalyzer.xcworkspace` in Xcode 8.2 and build the project (⌘-B).
83 | 1. `$ cd Build/MacOS`
84 | 1. `$ ./ibanalyzer /path/to/your/project`
85 |
86 | ## Attributions
87 |
88 | - [SourceKitten](https://github.com/jpsim/SourceKitten) – IBAnalyzer wouldn't be possible without it
89 | - [SwiftGen](https://github.com/AliSoftware/SwiftGen) – inspiration for `NibParser`
90 | - [Sourcery](https://github.com/krzysztofzablocki/Sourcery) – IBAnalyzer uses pretty much the same `Rakefile`
91 |
92 | ## Author
93 |
94 | Project initially started by [Arek Holko](http://holko.pl) ([@arekholko](https://twitter.com/arekholko) on Twitter).
95 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/rake
2 | ## Based on the code from Sourcery https://github.com/krzysztofzablocki/Sourcery/blob/master/Rakefile
3 |
4 | require 'pathname'
5 | require 'yaml'
6 | require 'json'
7 | require 'net/http'
8 | require 'uri'
9 |
10 | BUILD_DIR = 'build/'
11 |
12 | ## [ Utils ] ##################################################################
13 |
14 | def version_select
15 | # Find all Xcode 8 versions on this computer
16 | xcodes = `mdfind "kMDItemCFBundleIdentifier = 'com.apple.dt.Xcode' && kMDItemVersion = '9.*'"`.chomp.split("\n")
17 | if xcodes.empty?
18 | raise "\n[!!!] You need to have Xcode 9.x to compile IBAnalyzer.\n\n"
19 | end
20 | # Order by version and get the latest one
21 | vers = lambda { |path| `mdls -name kMDItemVersion -raw "#{path}"` }
22 | latest_xcode_version = xcodes.sort { |p1, p2| vers.call(p1) <=> vers.call(p2) }.last
23 | %Q(DEVELOPER_DIR="#{latest_xcode_version}/Contents/Developer" TOOLCHAINS=com.apple.dt.toolchain.XcodeDefault.xctoolchain)
24 | end
25 |
26 | def xcpretty(cmd)
27 | if `which xcpretty` && $?.success?
28 | sh "set -o pipefail && #{cmd} | xcpretty -c"
29 | else
30 | sh cmd
31 | end
32 | end
33 |
34 | def xcrun(cmd)
35 | xcpretty "#{version_select} xcrun #{cmd}"
36 | end
37 |
38 | def print_info(str)
39 | (red,clr) = (`tput colors`.chomp.to_i >= 8) ? %W(\e[33m \e[m) : ["", ""]
40 | puts red, "== #{str.chomp} ==", clr
41 | end
42 | ## [ Tests & Clean ] ##########################################################
43 |
44 | desc "Run the Unit Tests"
45 | task :tests do
46 | print_info "Running Unit Tests"
47 | xcrun %Q(xcodebuild -workspace IBAnalyzer.xcworkspace -scheme IBAnalyzer -sdk macosx test)
48 | end
49 |
50 | desc "Delete the build/ directory"
51 | task :clean do
52 | sh %Q(rm -fr build)
53 | end
54 |
55 | task :build do
56 | print_info "Building project"
57 | xcrun %Q(xcodebuild -workspace IBAnalyzer.xcworkspace -scheme IBAnalyzer -configuration Release -sdk macosx -derivedDataPath #{BUILD_DIR}/tmp/)
58 | sh %Q(rm -fr bin/IBAnalyzer.app)
59 | `mv #{BUILD_DIR}tmp/Build/Products/Release/IBAnalyzer.app bin/`
60 | sh %Q(rm -fr #{BUILD_DIR}tmp/)
61 | end
62 |
63 | ## [ Release ] ##########################################################
64 |
65 | namespace :release do
66 | desc 'Create a new release on GitHub, CocoaPods and Homebrew'
67 | task :new => [:check_versions, :build, :tests, :github, :cocoapods]
68 |
69 | def podspec_version(file = 'IBAnalyzer')
70 | JSON.parse(`bundle exec pod ipc spec #{file}.podspec`)["version"]
71 | end
72 |
73 | def log_result(result, label, error_msg)
74 | if result
75 | puts "#{label.ljust(25)} \u{2705}"
76 | else
77 | puts "#{label.ljust(25)} \u{274C} - #{error_msg}"
78 | end
79 | result
80 | end
81 |
82 | desc 'Check if all versions from the podspecs and CHANGELOG match'
83 | task :check_versions do
84 | results = []
85 |
86 | # Check if bundler is installed first, as we'll need it for the cocoapods task (and we prefer to fail early)
87 | `which bundler`
88 | results << log_result( $?.success?, 'Bundler installed', 'Please install bundler using `gem install bundler` and run `bundle install` first.')
89 |
90 | # Extract version from IBAnalyzer.podspec
91 | version = podspec_version
92 | puts "#{'IBAnalyzer.podspec'.ljust(25)} \u{1F449} #{version}"
93 |
94 | # Check if entry present in CHANGELOG
95 | changelog_entry = system(%Q{grep -q '^## #{Regexp.quote(version)}$' CHANGELOG.md})
96 | results << log_result(changelog_entry, "CHANGELOG, Entry added", "Please add an entry for #{version} in CHANGELOG.md")
97 |
98 | changelog_master = system(%q{grep -qi '^## Master' CHANGELOG.md})
99 | results << log_result(!changelog_master, "CHANGELOG, No master", 'Please remove entry for master in CHANGELOG')
100 |
101 | exit 1 unless results.all?
102 |
103 | print "Release version #{version} [Y/n]? "
104 | exit 2 unless (STDIN.gets.chomp == 'Y')
105 | end
106 |
107 | desc 'Create a zip containing all the prebuilt binaries'
108 | task :zip => [:clean] do
109 | sh %Q(mkdir -p "build")
110 | sh %Q(cp -r bin build/)
111 | `cp LICENSE README.md CHANGELOG.md build`
112 | `cd build; zip -r -X ibanalyzer-#{podspec_version}.zip .`
113 | end
114 |
115 | def post(url, content_type)
116 | uri = URI.parse(url)
117 | req = Net::HTTP::Post.new(uri, initheader = {'Content-Type' => content_type})
118 | yield req if block_given?
119 | req.basic_auth 'fastred', File.read('.apitoken').chomp
120 |
121 | response = Net::HTTP.start(uri.host, uri.port, :use_ssl => (uri.scheme == 'https')) do |http|
122 | http.request(req)
123 | end
124 | unless response.code == '201'
125 | puts "Error: #{response.code} - #{response.message}"
126 | puts response.body
127 | exit 3
128 | end
129 | JSON.parse(response.body)
130 | end
131 |
132 | desc 'Upload the zipped binaries to a new GitHub release'
133 | task :github => :zip do
134 | v = podspec_version
135 |
136 | changelog = `sed -n /'^## #{v}$'/,/'^## '/p CHANGELOG.md`.gsub(/^## .*$/,'').strip
137 | print_info "Releasing version #{v} on GitHub"
138 | puts changelog
139 |
140 | json = post('https://api.github.com/repos/fastred/IBAnalyzer/releases', 'application/json') do |req|
141 | req.body = { :tag_name => v, :name => v, :body => changelog, :draft => false, :prerelease => false }.to_json
142 | end
143 |
144 | upload_url = json['upload_url'].gsub(/\{.*\}/,"?name=IBAnalyzer-#{v}.zip")
145 | zipfile = "build/IBAnalyzer-#{v}.zip"
146 | zipsize = File.size(zipfile)
147 |
148 | print_info "Uploading ZIP (#{zipsize} bytes)"
149 | post(upload_url, 'application/zip') do |req|
150 | req.body_stream = File.open(zipfile, 'rb')
151 | req.add_field('Content-Length', zipsize)
152 | req.add_field('Content-Transfer-Encoding', 'binary')
153 | end
154 | end
155 |
156 | desc 'pod trunk push IBAnalyzer to CocoaPods'
157 | task :cocoapods do
158 | print_info "Pushing pod to CocoaPods Trunk"
159 | sh 'bundle exec pod trunk push IBAnalyzer.podspec --allow-warnings'
160 | end
161 | end
162 |
--------------------------------------------------------------------------------
/Resources/unnecessary-action@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastred/IBAnalyzer/c368cc8537cd1da842fab05ba17f5afd46964d2c/Resources/unnecessary-action@2x.png
--------------------------------------------------------------------------------
/Resources/unnecessary-outlet@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastred/IBAnalyzer/c368cc8537cd1da842fab05ba17f5afd46964d2c/Resources/unnecessary-outlet@2x.png
--------------------------------------------------------------------------------
/bin/ibanalyzer:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # This file serves just as a link
3 | # Based on: https://github.com/krzysztofzablocki/Sourcery/blob/master/bin/sourcery
4 |
5 | parent_path=$( cd "$(dirname "${BASH_SOURCE}")" ; pwd -P )
6 |
7 | "${parent_path}"/IBAnalyzer.app/Contents/MacOS/IBAnalyzer "$@"
8 |
--------------------------------------------------------------------------------