Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ let package = Package(
.package(url: "https://github.com/thoughtbot/Curry.git", from: "4.0.1"),
],
targets: [
.target(name: "SourceDocs", dependencies: [
.target(name: "SourceDocsLib", dependencies: [
"SourceKittenFramework",
"MarkdownGenerator",
"Rainbow",
"Commandant",
"Curry"
]),
.testTarget(name: "SourceDocsTests", dependencies: ["SourceDocs"]),
.target(name: "SourceDocs", dependencies: ["SourceDocsLib"]),
.testTarget(name: "SourceDocsTests", dependencies: ["SourceDocsLib"]),
.target(name: "SourceDocsDemo", dependencies: []),
]
)
31 changes: 0 additions & 31 deletions Sources/SourceDocs/Classes/SourceDocs.swift

This file was deleted.

3 changes: 2 additions & 1 deletion Sources/SourceDocs/main.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Foundation
import SourceDocsLib

SourceDocs().run()
run()
15 changes: 11 additions & 4 deletions Sources/SourceDocsDemo/SampleCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,20 @@ public protocol Animal {

/// Describes the state of domestication
///
/// ### h3 _this is italics_
/// _Italics_ are supported with a leading and trailing underscore
///
/// # h1 **this is bold**
/// **Bold** is supported with 2 leading and trailing asterisks
///
/// ## h2 WHAT
/// These are the supported headings using `#`:
///
/// # h1
///
/// ## h2
///
/// ### h3
///
/// #### h4
///
/// ###### h6
/// ---
/// ***
/// - domesticated: For animal that are domesticated.
Expand Down
14 changes: 14 additions & 0 deletions Sources/SourceDocsLib/Classes/ConsolePrinter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// ConsolePrinter.swift
// SourceDocs
//
// Created by Jim Hildensperger on 14/08/2018.
//

import Foundation

struct ConsolePrinter: Printer {
func print(_ cstring: UnsafePointer<Int8>!, _ stream: UnsafeMutablePointer<FILE>!) {
fputs(cstring, stream)
}
}
17 changes: 17 additions & 0 deletions Sources/SourceDocsLib/Classes/Constants.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Constants.swift
// SourceDocs
//
// Created by Jim Hildensperger on 13/08/2018.
//

import Foundation

struct Constants {
static let version = "0.6.0"
static let defaultOutputDirectory = "Documentation/Reference"
static let defaultContentsFilename = "README"
static let defaultStatusFilename = "documentation_status.json"
static let defaultCoverageSvgFilename = "documentation_coverage.svg"
static let defaultAccessLevelString = SwiftAccessLevel.public.rawValue
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct CoverageBadge: Writeable {
let basePath: String

var filePath: String {
return basePath + "/" + SourceDocs.defaultCoverageSvgFilename
return basePath + "/" + Constants.defaultCoverageSvgFilename
}

private var colorForCoverage: String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct DocumentationStatusFile: Writeable {
let status: DocumentationStatus

var filePath: String {
return basePath + "/" + SourceDocs.defaultStatusFilename
return basePath + "/" + Constants.defaultStatusFilename
}

func write() throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,44 +21,56 @@ class MarkdownIndex: Writeable {
let filePath: String

private let filename: String
private let accessLevel: SwiftAccessLevel
private var structs: [MarkdownObject] = []
private var classes: [MarkdownObject] = []
private var extensions: [MarkdownExtension] = []
private var enums: [MarkdownEnum] = []
private var protocols: [MarkdownProtocol] = []
private var typealiases: [MarkdownTypealias] = []

init(basePath: String, docs: [SwiftDocs], options: GenerateCommandOptions) {
init?(basePath: String, docs: [SwiftDocs], options: GenerateCommandOptions) {
self.basePath = basePath
self.filename = options.contentsFileName
self.filePath = basePath + "/" + filename
self.process(docs: docs, options: options)

guard let accessLevel = SwiftAccessLevel(rawValue: options.accessLevelString) else {
return nil
}

self.accessLevel = accessLevel

let markdownOptions = MarkdownOptions(collapsibleBlocks: options.collapsibleBlocks, tableOfContents: options.tableOfContents)
let dictionaries = docs.compactMap { $0.docsDictionary.bridge() as? SwiftDocDictionary }

process(dictionaries: dictionaries, markdownOptions: markdownOptions)
}

func write() throws {
let flattenedExtensions = self.flattenedExtensions()
let documenatables: [[Documentable]] = [protocols, structs, classes, enums, flattenedExtensions, typealiases]

printer.print("Generating Markdown documentation...\n".green, stdout)

fputs("Generating Markdown documentation...\n".green, stdout)

let status = [protocols, structs, classes, enums, flattenedExtensions, typealiases].compactMap {
guard let documentables = $0 as? [Documentable] else {
return nil
}

return documentables.reduce(DocumentationStatus()) { (result, documentable) in
return result + documentable.checkDocumentation()
let status = documenatables.compactMap {
$0.reduce(DocumentationStatus()) { (result, documentable) in
return result + documentable.getDocumentationStatus()
}
}.reduce(DocumentationStatus(), +)

guard status.interfaceCount > 0 else {
throw NSError(domain: "No interfaces for the access level: ", code: 9999, userInfo: nil)
}

let coverage = Int(status.precentage * 100)

var content: [MarkdownConvertible] = [
"""
# Reference Documentation
This Reference Documentation has been generated with
[SourceDocs v\(SourceDocs.version)](https://github.com/jhildensperger/SourceDocs).
[SourceDocs v\(Constants.version)](https://github.com/jhildensperger/SourceDocs).

![\(coverage)%](\(SourceDocs.defaultCoverageSvgFilename))
![\(coverage)%](\(Constants.defaultCoverageSvgFilename))
"""
]

Expand All @@ -72,45 +84,38 @@ class MarkdownIndex: Writeable {
try writeFile(file: CoverageBadge(coverage: coverage, basePath: basePath))
try writeFile(file: MarkdownFile(filename: filename, basePath: basePath, content: content))
try writeFile(file: DocumentationStatusFile(basePath: basePath, status: status))
fputs("Done 🎉\n".green, stdout)
printer.print("Done 🎉\n".green, stdout)
}

func addItem(from dictionary: SwiftDocDictionary, options: GenerateCommandOptions) {
let markdownOptions = MarkdownOptions(collapsibleBlocks: options.collapsibleBlocks, tableOfContents: options.tableOfContents)

if let value: String = dictionary.get(.kind), let kind = SwiftDeclarationKind(rawValue: value) {
if kind == .struct, let item = MarkdownObject(dictionary: dictionary, options: markdownOptions) {
func addItem(from dictionary: SwiftDocDictionary, markdownOptions: MarkdownOptions) {
if let value: String = dictionary[.kind], let kind = SwiftDeclarationKind(rawValue: value) {
if kind == .struct, let item = MarkdownObject(dictionary: dictionary, options: markdownOptions, accessLevel: accessLevel) {
structs.append(item)
} else if kind == .class, let item = MarkdownObject(dictionary: dictionary, options: markdownOptions) {
} else if kind == .class, let item = MarkdownObject(dictionary: dictionary, options: markdownOptions, accessLevel: accessLevel) {
classes.append(item)
} else if let item = MarkdownExtension(dictionary: dictionary, options: markdownOptions) {
} else if let item = MarkdownExtension(dictionary: dictionary, options: markdownOptions, accessLevel: accessLevel) {
extensions.append(item)
} else if let item = MarkdownEnum(dictionary: dictionary, options: markdownOptions) {
} else if let item = MarkdownEnum(dictionary: dictionary, options: markdownOptions, accessLevel: accessLevel) {
enums.append(item)
} else if let item = MarkdownProtocol(dictionary: dictionary, options: markdownOptions) {
} else if let item = MarkdownProtocol(dictionary: dictionary, options: markdownOptions, accessLevel: accessLevel) {
protocols.append(item)
} else if let item = MarkdownTypealias(dictionary: dictionary, options: markdownOptions) {
} else if let item = MarkdownTypealias(dictionary: dictionary, options: markdownOptions, accessLevel: accessLevel) {
typealiases.append(item)
}
}
}

// MARK: - Private

private func process(docs: [SwiftDocs], options: GenerateCommandOptions) {
let dictionaries = docs.compactMap { $0.docsDictionary.bridge() as? SwiftDocDictionary }
process(dictionaries: dictionaries, options: options)
}

private func process(dictionaries: [SwiftDocDictionary], options: GenerateCommandOptions) {
dictionaries.forEach { process(dictionary: $0, options: options) }
private func process(dictionaries: [SwiftDocDictionary], markdownOptions: MarkdownOptions) {
dictionaries.forEach { process(dictionary: $0, markdownOptions: markdownOptions) }
}

private func process(dictionary: SwiftDocDictionary, options: GenerateCommandOptions) {
addItem(from: dictionary, options: options)
private func process(dictionary: SwiftDocDictionary, markdownOptions: MarkdownOptions) {
addItem(from: dictionary, markdownOptions: markdownOptions)

if let substructure = dictionary[SwiftDocKey.substructure.rawValue] as? [SwiftDocDictionary] {
process(dictionaries: substructure, options: options)
process(dictionaries: substructure, markdownOptions: markdownOptions)
}
}

Expand All @@ -136,12 +141,12 @@ class MarkdownIndex: Writeable {
}

private func writeFile(file: Writeable) throws {
fputs(" Writing documentation file: \(file.filePath)", stdout)
printer.print(" Writing documentation file: \(file.filePath)", stdout)
do {
try file.write()
fputs(" ✔\n".green, stdout)
printer.print(" ✔\n".green, stdout)
} catch let error {
fputs(" ❌\n", stdout)
printer.print(" ❌\n", stdout)
throw error
}
}
Expand Down
31 changes: 31 additions & 0 deletions Sources/SourceDocsLib/Classes/SwiftAccessLevel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// SwiftAccessLevel.swift
// SourceDocs
//
// Created by Jim Hildensperger on 13/08/2018.
//

import Foundation

enum SwiftAccessLevel: String {
case `open`
case `public`
case `internal`
case `fileprivate`
case `private`

init?(sourceKitAccessibility: String) {
let rawValue = sourceKitAccessibility.replacingOccurrences(of: "source.lang.swift.accessibility.", with: "")
self.init(rawValue: rawValue)
}

func isGreaterThanOrEqual(to level: SwiftAccessLevel) -> Bool {
switch self {
case .open: return true
case .public: return level != .open
case .internal: return level != .open && level != .public
case .fileprivate: return level != .open && level != .public && level != .internal
case .private: return level != .open && level != .public && level != .internal && level != .fileprivate
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ struct CleanCommandOptions: OptionsProtocol {

static func evaluate(_ mode: CommandMode) -> Result<CleanCommandOptions, CommandantError<SourceDocsError>> {
return curry(self.init)
<*> mode <| Option(key: "output-folder", defaultValue: SourceDocs.defaultOutputDirectory,
usage: "Output directory (defaults to \(SourceDocs.defaultOutputDirectory)).")
<*> mode <| Option(key: "output-folder", defaultValue: Constants.defaultOutputDirectory,
usage: "Output directory (defaults to \(Constants.defaultOutputDirectory)).")
}
}

Expand All @@ -39,10 +39,10 @@ struct CleanCommand: CommandProtocol {
static func removeReferenceDocs(docsPath: String) throws {
var isDir: ObjCBool = false
if FileManager.default.fileExists(atPath: docsPath, isDirectory: &isDir) {
fputs("Removing reference documentation at '\(docsPath)'...".green, stdout)
printer.print("Removing reference documentation at '\(docsPath)'...".green, stdout)

guard let paths = try? FileManager.default.contentsOfDirectory(atPath: docsPath) else {
fputs(" ❌\n", stdout)
printer.print(" ❌\n", stdout)
throw NSError(domain: "file", code: 9999, userInfo: nil)
}

Expand All @@ -51,14 +51,14 @@ struct CleanCommand: CommandProtocol {
guard path.first != "." else { continue }
try FileManager.default.removeItem(atPath: docsPath.appending("/\(path)"))
} catch let error {
fputs(" ❌\n", stdout)
printer.print(" ❌\n", stdout)
throw error
}
}

fputs(" ✔".green + "\n", stdout)
printer.print(" ✔".green + "\n", stdout)
} else {
fputs("Did not find any reference docs at '\(docsPath)'.\n", stdout)
printer.print("Did not find any reference docs at '\(docsPath)'.\n", stdout)
}
}

Expand Down
Loading