When you add: import Danger to the top of your Dangerfile it exposes a bunch of stuff. First up, there arre the messaging functions

import DangerShellExecutor
import Darwin
import Darwin.C
import Foundation
import Logger
import OctoKit
import RequestKit
import SwiftOnoneSupport

struct BitBucketCloud: Decodable {
    /// The activities such as OPENING, CLOSING, MERGING or UPDATING a pull request
    let activities: [BitBucketCloud.Activity]

    /// The comments on the pull request
    let comments: [BitBucketCloud.Comment]

    /// The commits associated with the pull request
    let commits: [BitBucketCloud.Commit]

    /// The pull request and repository metadata
    let metadata: BitBucketMetadata

    /// The PR metadata
    let pr: BitBucketCloud.PullRequest
}

extension BitBucketCloud {
    struct PullRequest: Decodable {
        enum State: String, Decodable {
            case declined

            case merged

            case open

            case suspended
        }

        struct Participant {
            enum Role: String, Decodable {
                case reviewer

                case participant
            }

            /// Did they approve of the PR?
            let approved: Bool

            /// How did they contribute
            let role: BitBucketCloud.PullRequest.Participant.Role

            /// The user who participated in this PR
            let user: BitBucketCloud.User
        }

        /// The creator of the PR
        let author: BitBucketCloud.User

        /// Date when PR was created
        let createdOn: Date

        /// The text describing the PR
        let description: String

        /// The PR's destination
        let destination: BitBucketCloud.MergeRef

        /// PR's ID
        let id: Int

        /// People who have participated in the PR
        let participants: [BitBucketCloud.PullRequest.Participant]

        /// People requested as reviewers
        let reviewers: [BitBucketCloud.User]

        /// The PR's source, The repo Danger is running on
        let source: BitBucketCloud.MergeRef

        /// The pull request's current status.
        let state: BitBucketCloud.PullRequest.State

        /// Title of the pull request
        let title: String

        /// Date of last update
        let updatedOn: Date
    }
}

extension BitBucketCloud {
    struct MergeRef: Decodable {
        var branchName: String { get }

        /// Hash of the last commit
        var commitHash: String { get }

        let repository: BitBucketCloud.Repo
    }
}

extension BitBucketCloud {
    struct Repo {
        let fullName: String

        let name: String

        /// The uuid of the repository
        let uuid: String
    }
}

extension BitBucketCloud {
    struct User {
        /// The acount id of the user
        let accountId: String?

        /// The display name of user
        let displayName: String

        /// The nick name of the user
        let nickname: String?

        /// The uuid of the user
        let uuid: String
    }
}

extension BitBucketCloud {
    struct Commit {
        struct Author {}

        struct Parent {}

        /// The author of the commit, assumed to be the person who wrote the code.
        let author: BitBucketCloud.Commit.Author

        /// When the commit was commited to the project
        let date: Date

        /// The SHA for the commit
        let hash: String

        /// The commit's message
        let message: String
    }
}

extension BitBucketCloud {
    struct Comment {
        struct Inline {
            let from: Int?

            let to: Int?

            let path: String?
        }

        /// Content of the comment
        let content: BitBucketCloud.Content

        /// When the comment was created
        let createdOn: Date

        /// Was the comment deleted?
        let deleted: Bool

        let id: Int

        let inline: BitBucketCloud.Comment.Inline?

        let type: String

        /// When the comment was updated
        let updatedOn: Date

        /// The user that created the comment
        let user: BitBucketCloud.User
    }
}

extension BitBucketCloud {
    struct Content {
        let html: String

        let markup: String

        let raw: String
    }
}

extension BitBucketCloud {
    struct Activity {
        let comment: BitBucketCloud.Comment?
    }
}

struct BitBucketMetadata {
    /// The PR's ID
    var pullRequestID: String

    /// The complete repo slug including project slug.
    var repoSlug: String
}

struct BitBucketServer {
    /// The pull request and repository metadata
    let metadata: BitBucketMetadata

    /// The pull request metadata
    let pullRequest: BitBucketServer.PullRequest

    /// The commits associated with the pull request
    let commits: [BitBucketServer.Commit]

    /// The comments on the pull request
    let comments: [BitBucketServer.Comment]

    /// The activities such as OPENING, CLOSING, MERGING or UPDATING a pull request
    let activities: [BitBucketServer.Activity]
}

extension BitBucketServer {
    struct Activity {
        /// The activity's ID
        let id: Int

        /// Date activity created as number of mili seconds since the unix epoch
        let createdAt: Int

        /// The user that triggered the activity.
        let user: BitBucketServer.User

        /// The action the activity describes (e.g. "COMMENTED").
        let action: String

        /// In case the action was "COMMENTED" it will state the command specific action (e.g. "CREATED").
        let commentAction: String?
    }
}

extension BitBucketServer {
    struct Comment {
        /// The comment's id
        let id: Int

        /// Date comment created as number of mili seconds since the unix epoch
        let createdAt: Int

        /// The comment's author
        let user: BitBucketServer.User

        /// The action the user did (e.g. "COMMENTED")
        let action: String

        /// The SHA to which the comment was created
        let fromHash: String?

        /// The previous SHA to which the comment was created
        let previousFromHash: String?

        /// The next SHA after the comment was created
        let toHash: String?

        /// The SHA to which the comment was created
        let previousToHash: String?

        /// Action the user did (e.g. "ADDED") if it is a new task
        let commentAction: String?

        /// Detailed data of the comment
        let comment: BitBucketServer.Comment.Detail?

        struct Detail {
            /// The comment's id
            let id: Int

            /// The comment's version
            let version: Int

            /// The comment content
            let text: String

            /// The author of the comment
            let author: BitBucketServer.User

            /// Date comment created as number of mili seconds since the unix epoch
            let createdAt: Int

            /// Date comment updated as number of mili seconds since the unix epoch
            let updatedAt: Int

            /// Replys to the comment
            let comments: [BitBucketServer.Comment.Detail]

            /// Properties associated with the comment
            let properties: BitBucketServer.Comment.Detail.InnerProperties

            /// Tasks associated with the comment
            let tasks: [BitBucketServer.Comment.Detail.Task]

            struct Task {
                /// The tasks ID
                let id: Int

                /// Date activity created as number of mili seconds since the unix epoch
                let createdAt: Int

                /// The text of the task
                let text: String

                /// The state of the task (e.g. "OPEN")
                let state: String

                /// The author of the comment
                let author: BitBucketServer.User
            }

            struct InnerProperties {
                /// The ID of the repo
                let repositoryId: Int

                /// Slugs of linkd Jira issues
                let issues: [String]?
            }
        }
    }
}

extension BitBucketServer {
    struct Commit {
        /// The SHA for the commit
        let id: String

        /// The shortened SHA for the commit
        let displayId: String

        /// The author of the commit, assumed to be the person who wrote the code.
        let author: BitBucketServer.User

        /// The UNIX timestamp for when the commit was authored
        let authorTimestamp: Int

        /// The author of the commit, assumed to be the person who commited/merged the code into a project.
        let committer: BitBucketServer.User?

        /// When the commit was commited to the project
        let committerTimestamp: Int?

        /// The commit's message
        let message: String

        /// The commit's parents
        let parents: [BitBucketServer.Commit.Parent]

        struct Parent {
            /// The SHA for the commit
            let id: String

            /// The shortened SHA for the commit
            let displayId: String
        }
    }
}

extension BitBucketServer {
    struct PullRequest {
        /// The PR's ID
        let id: Int

        /// The API version
        let version: Int

        /// Title of the pull request.
        let title: String

        /// The description of the PR
        let description: String?

        /// The pull request's current status.
        let state: String

        /// Is PR open?
        let open: Bool

        /// Is PR closed?
        let closed: Bool

        /// Date PR created as number of mili seconds since the unix epoch
        let createdAt: Int

        /// Date PR updated as number of mili seconds since the unix epoch
        let updatedAt: Int?

        /// The PR submittor's reference
        let fromRef: BitBucketServer.MergeRef

        /// The repo Danger is running on
        let toRef: BitBucketServer.MergeRef

        /// Is the PR locked?
        let isLocked: Bool

        /// The creator of the PR
        let author: BitBucketServer.PullRequest.Participant

        /// People requested as reviewers
        let reviewers: [BitBucketServer.PullRequest.Reviewer]

        /// People who have participated in the PR
        let participants: [BitBucketServer.PullRequest.Participant]

        /// A user that is parecipating in the PR
        struct Participant {
            /// The BitBucket Server User
            let user: BitBucketServer.User
        }

        /// A user that reviewed the PR
        struct Reviewer {
            /// The BitBucket Server User
            let user: BitBucketServer.User

            /// The approval status
            let approved: Bool

            /// The commit SHA for the latest commit that was reviewed
            let lastReviewedCommit: String?
        }
    }
}

extension BitBucketServer {
    struct MergeRef {
        /// The branch name
        let id: String

        /// The human readable branch name
        let displayId: String

        /// The SHA for the latest commit
        let latestCommit: String

        /// Info of the associated repository
        let repository: BitBucketServer.Repo
    }
}

extension BitBucketServer {
    struct Repo {
        /// The repo name
        let name: String?

        /// The slug for the repo
        let slug: String

        /// The type of SCM tool, probably "git"
        let scmId: String

        /// Is the repo public?
        let isPublic: Bool

        /// Can someone fork thie repo?
        let forkable: Bool

        /// An abtraction for grouping repos
        let project: BitBucketServer.Project
    }
}

extension BitBucketServer {
    struct Project {
        /// The project unique id
        let id: Int

        /// The project's human readable project key
        let key: String

        /// The name of the project
        let name: String

        /// Is the project publicly available
        let isPublic: Bool

        let type: String
    }
}

extension BitBucketServer {
    struct User {
        /// The unique user ID
        let id: Int?

        /// The name of the user
        let name: String

        /// The name to use when referencing the user
        let displayName: String?

        /// The email for the user
        let emailAddress: String?

        /// Is the account active
        let active: Bool?

        /// The user's slug for URLs
        let slug: String?

        /// The type of a user, "NORMAL" being a typical user3
        let type: String?
    }
}

struct DSL: Decodable {
    /// The root danger import
    let danger: DangerDSL
}

func Danger() -> DangerDSL

struct DangerDSL: Decodable {
    let git: Git

    private(set) var github: GitHub! { get }

    let bitbucketCloud: BitBucketCloud!

    let bitbucketServer: BitBucketServer!

    let gitLab: GitLab!

    let utils: DangerUtils

    /// Creates a new instance by decoding from the given decoder.
    ///
    /// This initializer throws an error if reading from the decoder fails, or
    /// if the data read is corrupted or otherwise invalid.
    ///
    /// - Parameter decoder: The decoder to read data from.
    init(from decoder: Decoder) throws
}

extension DangerDSL {
    /// Fails on the Danger report
    var fails: [Violation] { get }

    /// Warnings on the Danger report
    var warnings: [Violation] { get }

    /// Messages on the Danger report
    var messages: [Violation] { get }

    /// Markdowns on the Danger report
    var markdowns: [Violation] { get }

    /// Adds a warning message to the Danger report
    ///
    /// - Parameter message: A markdown-ish
    func warn(_ message: String)

    /// Adds an inline warning message to the Danger report
    func warn(message: String, file: String, line: Int)

    /// Adds a warning message to the Danger report
    ///
    /// - Parameter message: A markdown-ish
    func fail(_ message: String)

    /// Adds an inline fail message to the Danger report
    func fail(message: String, file: String, line: Int)

    /// Adds a warning message to the Danger report
    ///
    /// - Parameter message: A markdown-ish
    func message(_ message: String)

    /// Adds an inline message to the Danger report
    func message(message: String, file: String, line: Int)

    /// Adds a warning message to the Danger report
    ///
    /// - Parameter message: A markdown-ish
    func markdown(_ message: String)

    /// Adds an inline message to the Danger report
    func markdown(message: String, file: String, line: Int)

    /// Adds an inline suggestion to the Danger report (sends a normal message if suggestions are not supported)
    func suggestion(code: String, file: String, line: Int)
}

/// Utility functions that make Dangerfiles easier to write
struct DangerUtils {
    /// Let's you go from a file path to the contents of the file
    /// with less hassle.
    ///
    /// It specifically assumes golden path code so Dangerfiles
    /// don't have to include error handlings - an error will
    /// exit evaluation entirely as it should only happen at dev-time.
    ///
    /// - Parameter file: the file reference from git.modified/creasted/deleted etc
    /// - Returns: the file contents, or bails
    func readFile(_ file: File) -> String

    /// Returns the line number of the lines that contain a specific string in a file
    ///
    /// - Parameter string: The string you want to search
    /// - Parameter file: The file path of the file where you want to search the string
    /// - Returns: the line number of the lines where the passed string is contained
    func lines(for string: String, inFile file: File) -> [Int]

    /// Gives you the ability to cheaply run a command and read the
    /// output without having to mess around
    ///
    /// It generally assumes that the command will pass, as you only get
    /// a string of the STDOUT. If you think your command could/should fail
    /// then you want to use `spawn` instead.
    ///
    /// - Parameter command: The first part of the command
    /// - Parameter arguments: An optional array of arguements to pass in extra
    /// - Returns: the stdout from the command
    func exec(_ command: String, arguments: [String] = []) -> String

    /// Gives you the ability to cheaply run a command and read the
    /// output without having to mess around too much, and exposes
    /// command errors in a pretty elegant way.
    ///
    /// - Parameter command: The first part of the command
    /// - Parameter arguments: An optional array of arguements to pass in extra
    /// - Returns: the stdout from the command
    func spawn(_ command: String, arguments: [String] = []) throws -> String

    /// Gives you the diff for a single file
    ///
    /// - Parameter file: The file path
    /// - Returns: File diff or error
    func diff(forFile file: String, sourceBranch: String) -> Result<FileDiff, Error>

    /// Converts an asynchronous function to synchronous.
    ///
    /// - Parameter body: The async function must be called inside this body and closure provided as parameter must be executed on completion
    /// - Returns: The value returned by the async function
    func sync<T>(_ body: (@escaping (T) -> Void) -> Void) -> T
}

extension DangerUtils {
    @dynamicMemberLookup struct Environment {
        subscript(dynamicMember _: String) -> DangerUtils.Environment.Value? { get }
    }
}

extension DangerUtils.Environment {
    enum Value: CustomStringConvertible, Equatable {
        case boolean(Bool)

        case string(String)

        /// A textual representation of this instance.
        ///
        /// Calling this property directly is discouraged. Instead, convert an
        /// instance of any type to a string by using the `String(describing:)`
        /// initializer. This initializer works with any type, and uses the custom
        /// `description` property for types that conform to
        /// `CustomStringConvertible`:
        ///
        ///     struct Point: CustomStringConvertible {
        ///         let x: Int, y: Int
        ///
        ///         var description: String {
        ///             return "(\(x), \(y))"
        ///         }
        ///     }
        ///
        ///     let p = Point(x: 21, y: 30)
        ///     let s = String(describing: p)
        ///     print(s)
        ///     // Prints "(21, 30)"
        ///
        /// The conversion of `p` to a string in the assignment to `s` uses the
        /// `Point` type's `description` property.
        var description: String { get }
    }
}

/// A simple typealias for strings representing files
typealias File = String

struct FileDiff: Equatable, CustomStringConvertible {
    var filePath: String { get }

    var changes: FileDiff.Changes { get }

    /// A textual representation of this instance.
    ///
    /// Calling this property directly is discouraged. Instead, convert an
    /// instance of any type to a string by using the `String(describing:)`
    /// initializer. This initializer works with any type, and uses the custom
    /// `description` property for types that conform to
    /// `CustomStringConvertible`:
    ///
    ///     struct Point: CustomStringConvertible {
    ///         let x: Int, y: Int
    ///
    ///         var description: String {
    ///             return "(\(x), \(y))"
    ///         }
    ///     }
    ///
    ///     let p = Point(x: 21, y: 30)
    ///     let s = String(describing: p)
    ///     print(s)
    ///     // Prints "(21, 30)"
    ///
    /// The conversion of `p` to a string in the assignment to `s` uses the
    /// `Point` type's `description` property.
    var description: String { get }
}

extension FileDiff {
    enum Changes: Equatable {
        case created(addedLines: [String])

        case deleted(deletedLines: [String])

        case modified(hunks: [FileDiff.Hunk])

        case renamed(oldPath: String, hunks: [FileDiff.Hunk])
    }

    struct Hunk: Equatable, CustomStringConvertible {
        let oldLineStart: Int

        let oldLineSpan: Int

        let newLineStart: Int

        let newLineSpan: Int

        let lines: [FileDiff.Line]

        /// A textual representation of this instance.
        ///
        /// Calling this property directly is discouraged. Instead, convert an
        /// instance of any type to a string by using the `String(describing:)`
        /// initializer. This initializer works with any type, and uses the custom
        /// `description` property for types that conform to
        /// `CustomStringConvertible`:
        ///
        ///     struct Point: CustomStringConvertible {
        ///         let x: Int, y: Int
        ///
        ///         var description: String {
        ///             return "(\(x), \(y))"
        ///         }
        ///     }
        ///
        ///     let p = Point(x: 21, y: 30)
        ///     let s = String(describing: p)
        ///     print(s)
        ///     // Prints "(21, 30)"
        ///
        /// The conversion of `p` to a string in the assignment to `s` uses the
        /// `Point` type's `description` property.
        var description: String { get }
    }

    struct Line: Equatable, CustomStringConvertible {
        /// A textual representation of this instance.
        ///
        /// Calling this property directly is discouraged. Instead, convert an
        /// instance of any type to a string by using the `String(describing:)`
        /// initializer. This initializer works with any type, and uses the custom
        /// `description` property for types that conform to
        /// `CustomStringConvertible`:
        ///
        ///     struct Point: CustomStringConvertible {
        ///         let x: Int, y: Int
        ///
        ///         var description: String {
        ///             return "(\(x), \(y))"
        ///         }
        ///     }
        ///
        ///     let p = Point(x: 21, y: 30)
        ///     let s = String(describing: p)
        ///     print(s)
        ///     // Prints "(21, 30)"
        ///
        /// The conversion of `p` to a string in the assignment to `s` uses the
        /// `Point` type's `description` property.
        var description: String { get }
    }
}

enum FileType: String, Equatable, CaseIterable {
    case h

    case json

    case m

    case markdown

    case mm

    case pbxproj

    case plist

    case storyboard

    case swift

    case xcscheme

    case yaml

    case yml
}

extension FileType {
    var `extension`: String { get }
}

/// The git specific metadata for a pull request.
struct Git {
    /// Modified filepaths relative to the git root.
    let modifiedFiles: [File]

    /// Newly created filepaths relative to the git root.
    let createdFiles: [File]

    /// Removed filepaths relative to the git root.
    let deletedFiles: [File]

    let commits: [Git.Commit]
}

extension Git {
    /// A platform agnostic reference to a git commit.
    struct Commit: Equatable {
        /// The author of a commit.
        struct Author: Equatable {
            /// The display name for the author.
            let name: String

            /// The email for the author.
            let email: String

            /// The ISO8601 date string for the commit.
            let date: String
        }

        /// The SHA for the commit.
        let sha: String?

        /// Who wrote the commit.
        let author: Git.Commit.Author

        /// Who shipped the code.
        let committer: Git.Commit.Author

        /// The message for the commit.
        let message: String

        /// SHAs for the commit's parents.
        let parents: [String]?

        /// The URL for the commit.
        let url: String?
    }
}

extension Git.Commit: Decodable {}

extension Git.Commit.Author: Decodable {}

/// The GitHub metadata for your pull request.
struct GitHub: Decodable {
    let issue: GitHub.Issue

    let pullRequest: GitHub.PullRequest

    let commits: [GitHub.Commit]

    let reviews: [GitHub.Review]

    let requestedReviewers: GitHub.RequestedReviewers

    internal(set) var api: OctoKit.Octokit! { get }
}

extension GitHub {
    struct PullRequest {
        enum PullRequestState: String, Decodable {
            case open

            case closed

            case merged

            case locked
        }

        /// The number of the pull request.
        let number: Int

        /// The title of the pull request.
        let title: String

        /// The markdown body message of the pull request.
        let body: String?

        /// The user who submitted the pull request.
        let user: GitHub.User

        /// The user who is assigned to the pull request.
        let assignee: GitHub.User?

        /// The users who are assigned to the pull request.
        let assignees: [GitHub.User]?

        /// The ISO8601 date string for when the pull request was created.
        let createdAt: Date

        /// The ISO8601 date string for when the pull request was updated.
        let updatedAt: Date

        /// The ISO8601 date string for when the pull request was closed.
        let closedAt: Date?

        /// The ISO8601 date string for when the pull request was merged.
        let mergedAt: Date?

        /// The merge reference for the _other_ repo.
        let head: GitHub.MergeRef

        /// The merge reference for _this_ repo.
        let base: GitHub.MergeRef

        /// The state for the pull request: open, closed, locked, merged.
        let state: GitHub.PullRequest.PullRequestState

        /// A boolean indicating if the pull request has been locked to contributors only.
        let isLocked: Bool

        /// A boolean indicating if the pull request has been merged.
        let isMerged: Bool?

        /// The number of commits in the pull request.
        let commitCount: Int?

        /// The number of comments in the pull request.
        let commentCount: Int?

        /// The number of review-specific comments in the pull request.
        let reviewCommentCount: Int?

        /// The number of added lines in the pull request.
        let additions: Int?

        /// The number of deleted lines in the pull request.
        let deletions: Int?

        /// The number of files changed in the pull request.
        let changedFiles: Int?

        /// The milestone of the pull request
        let milestone: GitHub.Milestone?

        /// The link back to this PR as user-facing
        let htmlUrl: String

        /// The draft state of the pull request
        let draft: Bool?

        /// Possible link relations
        let links: GitHub.PullRequest.Link
    }
}

extension GitHub {
    /// A GitHub user account.
    struct User {
        enum UserType: String, Decodable {
            case user

            case organization

            case bot
        }

        /// The UUID for the user organization.
        let id: Int

        /// The handle for the user or organization.
        let login: String

        /// The type of user: user, organization, or bot.
        let userType: GitHub.User.UserType
    }
}

extension GitHub {
    /// A GitHub team.
    struct Team {
        /// The UUID for the team.
        let id: Int

        /// The team name
        let name: String
    }
}

extension GitHub {
    /// Represents the payload for a PR's requested reviewers value.
    struct RequestedReviewers {
        /// The list of users of whom a review has been requested.
        let users: [GitHub.User]

        /// The list of teams of whom a review has been requested.
        let teams: [GitHub.Team]
    }
}

extension GitHub {
    /// Represents 'head' in PR
    struct MergeRef {
        /// The human display name for the merge reference, e.g. "artsy:master".
        let label: String

        /// The reference point for the merge, e.g. "master"
        let ref: String

        /// The reference point for the merge, e.g. "704dc55988c6996f69b6873c2424be7d1de67bbe"
        let sha: String

        /// The user that owns the merge reference e.g. "artsy"
        let user: GitHub.User

        /// The repo from which the reference comes from
        let repo: GitHub.Repo
    }
}

extension GitHub {
    struct Repo {
        /// Generic UUID.
        let id: Int

        /// The name of the repo, e.g. "danger-swift".
        let name: String

        /// The full name of the owner + repo, e.g. "Danger/danger-swift"
        let fullName: String

        /// The owner of the repo.
        let owner: GitHub.User

        /// A boolean stating whether the repo is publicly accessible.
        let isPrivate: Bool

        /// A textual description of the repo.
        let description: String?

        /// A boolean stating whether the repo is a fork.
        let isFork: Bool

        /// The root web URL for the repo, e.g. https://github.com/artsy/emission
        let htmlURL: String
    }
}

extension GitHub {
    struct Review {
        enum State: String, Decodable {
            case approved

            case requestedChanges

            case comment

            case pending

            case dismissed
        }

        /// The body of the review (if a review was made).
        let body: String?

        /// The commit ID the review was made on (if a review was made).
        let commitId: String?

        /// The id for the review (if a review was made).
        let id: Int?

        /// The state of the review (if a review was made).
        let state: GitHub.Review.State?

        /// The date when the review was submitted
        let submittedAt: Date

        /// The user who has completed the review or has been requested to review.
        let user: GitHub.User
    }
}

extension GitHub {
    /// A GitHub specific implementation of a git commit.
    struct Commit {
        /// The SHA for the commit.
        let sha: String

        /// The raw commit metadata.
        let commit: GitHub.Commit.CommitData

        /// The URL for the commit on GitHub.
        let url: String

        /// The GitHub user who wrote the code.
        let author: GitHub.User?

        /// The GitHub user who shipped the code.
        let committer: GitHub.User?

        /// Creates a new instance by decoding from the given decoder.
        ///
        /// This initializer throws an error if reading from the decoder fails, or
        /// if the data read is corrupted or otherwise invalid.
        ///
        /// - Parameter decoder: The decoder to read data from.
        init(from decoder: Decoder) throws
    }
}

extension GitHub {
    struct Issue {
        enum State: String, Decodable {
            case open

            case closed

            case locked
        }

        struct Label {
            /// The id number of this label.
            let id: Int

            /// The URL that links to this label.
            let url: String

            /// The name of the label.
            let name: String

            /// The color associated with this label.
            let color: String
        }

        /// The id number of the issue
        let id: Int

        /// The number of the issue.
        let number: Int

        /// The title of the issue.
        let title: String

        /// The user who created the issue.
        let user: GitHub.User

        /// The state for the issue: open, closed, locked.
        let state: GitHub.Issue.State

        /// A boolean indicating if the issue has been locked to contributors only.
        let isLocked: Bool

        /// The markdown body message of the issue.
        let body: String?

        /// The comment number of comments for the issue.
        let commentCount: Int

        /// The user who is assigned to the issue.
        let assignee: GitHub.User?

        /// The users who are assigned to the issue.
        let assignees: [GitHub.User]

        /// The milestone of this issue
        let milestone: GitHub.Milestone?

        /// The ISO8601 date string for when the issue was created.
        let createdAt: Date

        /// The ISO8601 date string for when the issue was updated.
        let updatedAt: Date

        /// The ISO8601 date string for when the issue was closed.
        let closedAt: Date?

        /// The labels associated with this issue.
        let labels: [GitHub.Issue.Label]
    }
}

extension GitHub {
    struct Milestone {
        enum State: String, Decodable {
            case open

            case closed

            case all
        }

        /// The id number of this milestone
        let id: Int

        /// The number of this milestone
        let number: Int

        /// The state of this milestone: open, closed, all
        let state: GitHub.Milestone.State

        /// The title of this milestone
        let title: String

        /// The description of this milestone.
        let description: String?

        /// The user who created this milestone.
        let creator: GitHub.User

        /// The number of open issues in this milestone
        let openIssues: Int

        /// The number of closed issues in this milestone
        let closedIssues: Int

        /// The ISO8601 date string for when this milestone was created.
        let createdAt: Date

        /// The ISO8601 date string for when this milestone was updated.
        let updatedAt: Date

        /// The ISO8601 date string for when this milestone was closed.
        let closedAt: Date?

        /// The ISO8601 date string for the due of this milestone.
        let dueOn: Date?
    }
}

extension GitHub.PullRequest {
    /// Pull Requests have possible link relations
    ///
    /// - See:
    ///   [Reference](https://docs.github.com/en/rest/reference/pulls#link-relations)
    struct Link {
        struct Relation, ExpressibleByStringLiteral {
            let href: String

            /// Creates an instance initialized to the given string value.
            ///
            /// - Parameter value: The value of the new instance.
            init(stringLiteral value: String)
        }

        /// The API location of the Pull Request.
        let `self`: GitHub.PullRequest.Link.Relation

        /// The HTML location of the Pull Request.
        let html: GitHub.PullRequest.Link.Relation

        /// The API location of the Pull Request's Issue.
        let issue: GitHub.PullRequest.Link.Relation

        /// The API location of the Pull Request's Issue comments.
        let comments: GitHub.PullRequest.Link.Relation

        /// The API location of the Pull Request's Review comments.
        let reviewComments: GitHub.PullRequest.Link.Relation

        /// The URL template to construct the API location for a Review comment in the Pull Request's repository.
        let reviewComment: GitHub.PullRequest.Link.Relation

        /// The API location of the Pull Request's commits.
        let commits: GitHub.PullRequest.Link.Relation

        /// The API location of the Pull Request's commit statuses, which are the statuses of its head branch.
        let statuses: GitHub.PullRequest.Link.Relation
    }
}

extension GitHub.Commit {
    /// A GitHub specific implementation of a github commit.
    struct CommitData: Equatable, Decodable {
        /// The SHA for the commit.
        let sha: String?

        /// Who wrote the commit.
        let author: Git.Commit.Author

        /// Who shipped the code.
        let committer: Git.Commit.Author

        /// The message for the commit.
        let message: String

        /// SHAs for the commit's parents.
        let parents: [String]?

        /// The URL for the commit.
        let url: String
    }
}

struct GitLab: Decodable {
    enum CodingKeys: String, CodingKey {
        case mergeRequest

        case metadata
    }

    let mergeRequest: GitLab.MergeRequest

    let metadata: GitLab.Metadata
}

extension GitLab {
    struct Metadata {
        let pullRequestID: String

        let repoSlug: String
    }
}

extension GitLab {
    struct MergeRequest {
        enum State: String, Decodable {
            case closed

            case locked

            case merged

            case opened
        }

        struct Milestone {
            enum ParentIdentifier: Equatable {
                case group(Int)

                case project(Int)

                var id: Int { get }

                var isGroup: Bool { get }

                var isProject: Bool { get }
            }

            enum CodingKeys: String, CodingKey {
                case createdAt

                case description

                case dueDate

                case id

                case iid

                case projectId

                case groupId

                case startDate

                case state

                case title

                case updatedAt

                case webUrl
            }

            enum State: String, Decodable {
                case active

                case closed
            }

            let createdAt: Date

            let description: String

            let dueDate: Date?

            let id: Int

            let iid: Int

            /// An unified identifier for [project milestone](https://docs.gitlab.com/ee/api/milestones.html)'s `project_id` \
            /// and [group milestone](https://docs.gitlab.com/ee/api/group_milestones.html)'s `group_id`.
            let parent: GitLab.MergeRequest.Milestone.ParentIdentifier

            let startDate: Date?

            let state: GitLab.MergeRequest.Milestone.State

            let title: String

            let updatedAt: Date

            let webUrl: String
        }

        struct TimeStats {
            enum CodingKeys: String, CodingKey {
                case humanTimeEstimate

                case humanTimeSpent

                case timeEstimate

                case totalTimeSpent
            }

            let humanTimeEstimate: Int?

            let humanTimeSpent: Int?

            let timeEstimate: Int

            let totalTimeSpent: Int
        }

        struct DiffRefs {}

        struct Pipeline {
            enum Status: String, Decodable {
                case canceled

                case failed

                case pending

                case running

                case skipped

                case success
            }

            enum CodingKeys: String, CodingKey {
                case id

                case ref

                case sha

                case status

                case webUrl
            }

            let id: Int

            let ref: String

            let sha: String

            let status: GitLab.MergeRequest.Pipeline.Status

            let webUrl: String
        }

        enum CodingKeys: String, CodingKey {
            case allowCollaboration

            case allowMaintainerToPush

            case approvalsBeforeMerge

            case assignee

            case assignees

            case author

            case changesCount

            case closedAt

            case closedBy

            case description

            case diffRefs

            case downvotes

            case firstDeployedToProductionAt

            case forceRemoveSourceBranch

            case id

            case iid

            case latestBuildStartedAt

            case latestBuildFinishedAt

            case labels

            case mergeCommitSha

            case mergedAt

            case mergedBy

            case mergeOnPipelineSuccess

            case milestone

            case pipeline

            case projectId

            case sha

            case shouldRemoveSourceBranch

            case sourceBranch

            case sourceProjectId

            case state

            case subscribed

            case targetBranch

            case targetProjectId

            case timeStats

            case title

            case upvotes

            case userMergeData

            case userNotesCount

            case webUrl

            case workInProgress
        }

        let allowCollaboration: Bool?

        let allowMaintainerToPush: Bool?

        let approvalsBeforeMerge: Int?

        let assignee: GitLab.User?

        let assignees: [GitLab.User]?

        let author: GitLab.User

        let changesCount: String

        let closedAt: Date?

        let closedBy: GitLab.User?

        let description: String

        let diffRefs: GitLab.MergeRequest.DiffRefs

        let downvotes: Int

        let firstDeployedToProductionAt: Date?

        let forceRemoveSourceBranch: Bool?

        let id: Int

        let iid: Int

        let latestBuildFinishedAt: Date?

        let latestBuildStartedAt: Date?

        let labels: [String]

        let mergeCommitSha: String?

        let mergedAt: Date?

        let mergedBy: GitLab.User?

        let mergeOnPipelineSuccess: Bool

        let milestone: GitLab.MergeRequest.Milestone?

        let pipeline: GitLab.MergeRequest.Pipeline?

        let projectId: Int

        let sha: String

        let shouldRemoveSourceBranch: Bool?

        let sourceBranch: String

        let sourceProjectId: Int

        let state: GitLab.MergeRequest.State

        let subscribed: Bool

        let targetBranch: String

        let targetProjectId: Int

        let timeStats: GitLab.MergeRequest.TimeStats

        let title: String

        let upvotes: Int

        let userNotesCount: Int

        let webUrl: String

        let workInProgress: Bool

        var userCanMerge: Bool { get }
    }
}

extension GitLab {
    struct User {
        enum CodingKeys: String, CodingKey {
            case avatarUrl

            case id

            case name

            case state

            case username

            case webUrl
        }

        enum State: String, Decodable {
            case active

            case blocked
        }

        let avatarUrl: String?

        let id: Int

        let name: String

        let state: GitLab.User.State

        let username: String

        let webUrl: String
    }
}

extension GitLab.MergeRequest.Milestone {
    /// Creates a new instance by decoding from the given decoder.
    ///
    /// This initializer throws an error if reading from the decoder fails, or
    /// if the data read is corrupted or otherwise invalid.
    ///
    /// - Parameter decoder: The decoder to read data from.
    init(from decoder: Decoder) throws
}

/// Meta information for showing in the text info
struct Meta: Encodable {}

/// The SwiftLint plugin has been embedded inside Danger, making
/// it usable out of the box.
enum SwiftLint {
    enum LintStyle {
        /// Lints all the files instead of only the modified and created files.
        /// - Parameters:
        ///   - directory: Optional property to set the --path to execute at.
        case all(directory: String?)

        /// Only lints the modified and created files with `.swift` extension.
        /// - Parameters:
        ///   - directory: Optional property to set the --path to execute at.
        case modifiedAndCreatedFiles(directory: String?)

        /// Lints only the given files. This can be useful to do some manual filtering.
        /// The files will be filtered on `.swift` only.
        case files([File])
    }

    enum SwiftlintPath {
        case swiftPackage(String)

        case bin(String)
    }

    /// This method is deprecated in favor of
    @available(*, deprecated, message: "Use the lint(_ lintStyle ..) method instead.")
    static func lint(inline: Bool = false, directory: String? = nil, configFile: String? = nil, strict: Bool = false, quiet: Bool = true, lintAllFiles: Bool = false, swiftlintPath: String? = nil) -> [SwiftLintViolation]

    /// When the swiftlintPath is not specified,
    /// it uses by default swift run swiftlint if the Package.swift in your root folder contains swiftlint as dependency,
    /// otherwise calls directly the swiftlint command
    @available(*, deprecated, message: "Use the lint(_ lintStyle ..) method instead.")
    static func lint(_ lintStyle: SwiftLint.LintStyle = .modifiedAndCreatedFiles(directory: nil), inline: Bool = false, configFile: String? = nil, strict: Bool = false, quiet: Bool = true, swiftlintPath: String?) -> [SwiftLintViolation]

    /// This is the main entry point for linting Swift in PRs.
    ///
    /// When the swiftlintPath is not specified,
    /// it uses by default swift run swiftlint if the Package.swift in your root folder contains swiftlint as dependency,
    /// otherwise calls directly the swiftlint command
    static func lint(_ lintStyle: SwiftLint.LintStyle = .modifiedAndCreatedFiles(directory: nil), inline: Bool = false, configFile: String? = nil, strict: Bool = false, quiet: Bool = true, swiftlintPath: SwiftLint.SwiftlintPath? = nil) -> [SwiftLintViolation]
}

struct SwiftLintViolation: Decodable {
    enum Severity: String, Decodable {
        case warning

        case error
    }

    internal(set) var ruleID: String { get }

    internal(set) var reason: String { get }

    internal(set) var line: Int { get }

    internal(set) var severity: SwiftLintViolation.Severity { get }

    internal(set) var file: String { get }

    func toMarkdown() -> String
}

/// The result of a warn, message, or fail.
struct Violation: Encodable {}

/// Adds a warning message to the Danger report
///
/// - Parameter message: A markdown-ish
func fail(_ message: String)

/// Adds an inline fail message to the Danger report
func fail(message: String, file: String, line: Int)

/// Fails on the Danger report
var fails: [Violation] { get }

/// Adds a warning message to the Danger report
///
/// - Parameter message: A markdown-ish
func markdown(_ message: String)

/// Adds an inline message to the Danger report
func markdown(message: String, file: String, line: Int)

/// Markdowns on the Danger report
var markdowns: [Violation] { get }

/// Adds a warning message to the Danger report
///
/// - Parameter message: A markdown-ish
func message(_ message: String)

/// Adds an inline message to the Danger report
func message(message: String, file: String, line: Int)

/// Messages on the Danger report
var messages: [Violation] { get }

/// Adds an inline suggestion to the Danger report (sends a normal message if suggestions are not supported)
func suggestion(code: String, file: String, line: Int)

/// Adds a warning message to the Danger report
///
/// - Parameter message: A markdown-ish
func warn(_ message: String)

/// Adds an inline warning message to the Danger report
func warn(message: String, file: String, line: Int)

/// Warnings on the Danger report
var warnings: [Violation] { get }

extension Optional where Wrapped == DangerUtils.Environment.Value {
    func getString(default defaultString: String) -> String

    func getBoolean(default defaultBoolean: Bool) -> Bool
}

extension DateFormatter {
    static var defaultDateFormatter: DateFormatter { get }

    static var onlyDateDateFormatter: DateFormatter { get }

    /// Handles multiple date format inside models.
    static func dateFormatterHandler(_ decoder: Decoder) throws -> Date
}

extension String {
    var fileType: FileType? { get }

    var name: String { get }
}

/// Fails on the Danger report
let fails: [Violation] { get }

/// Warnings on the Danger report
let warnings: [Violation] { get }

/// Messages on the Danger report
let messages: [Violation] { get }

/// Markdowns on the Danger report
let markdowns: [Violation] { get }