{"action":"created","comment":{"url":"https://api.github.com/repos/realm/SwiftLint/pulls/comments/50613775","id":50613775,"diff_hunk":"@@ -0,0 +1,39 @@\n+//\n+//  SeverityConfig.swift\n+//  SwiftLint\n+//\n+//  Created by Scott Hoyt on 1/20/16.\n+//  Copyright © 2016 Realm. All rights reserved.\n+//\n+\n+import Foundation\n+\n+public struct SeverityConfig: RuleConfig, Equatable {\n+    var severity: ViolationSeverity\n+\n+    public init(_ severity: ViolationSeverity) {\n+        self.severity = severity\n+    }\n+\n+    public mutating func setConfig(config: AnyObject) throws {\n+        guard\n+            // swiftlint:disable:next line_length\n+            let value = config as? String ?? (config as? [String: AnyObject])?[\"severity\"] as? String,\n+            let severity = ViolationSeverity(unnormalized: value) else {\n+                throw ConfigurationError.UnknownConfiguration\n+        }\n+        self.severity = severity\n+    }\n+}\n+\n+public func == (lhs: SeverityConfig, rhs: SeverityConfig) -> Bool {\n+    return lhs.severity == rhs.severity\n+}\n+\n+// MARK: - ViolationSeverity extensions\n+\n+public extension ViolationSeverity {\n+    init?(unnormalized: String) {","path":"Source/SwiftLintFramework/Rules/RuleConfigs/SeverityConfig.swift","position":36,"original_position":36,"commit_id":"2ffab8cd356faa20eb62ef406b48589516cc4e15","original_commit_id":"2ffab8cd356faa20eb62ef406b48589516cc4e15","user":{"login":"jpsim","id":474794,"avatar_url":"https://avatars.githubusercontent.com/u/474794?v=3","gravatar_id":"","url":"https://api.github.com/users/jpsim","html_url":"https://github.com/jpsim","followers_url":"https://api.github.com/users/jpsim/followers","following_url":"https://api.github.com/users/jpsim/following{/other_user}","gists_url":"https://api.github.com/users/jpsim/gists{/gist_id}","starred_url":"https://api.github.com/users/jpsim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpsim/subscriptions","organizations_url":"https://api.github.com/users/jpsim/orgs","repos_url":"https://api.github.com/users/jpsim/repos","events_url":"https://api.github.com/users/jpsim/events{/privacy}","received_events_url":"https://api.github.com/users/jpsim/received_events","type":"User","site_admin":false},"body":"This feels out of place. Since it's only used once, in this file, I think you should just pass `ViolationSeverity(rawValue: value.lowercaseString.capitalizedString)` at the call site in `setConfig` above.","created_at":"2016-01-23T02:15:07Z","updated_at":"2016-01-23T02:15:07Z","html_url":"https://github.com/realm/SwiftLint/pull/391#discussion_r50613775","pull_request_url":"https://api.github.com/repos/realm/SwiftLint/pulls/391","_links":{"self":{"href":"https://api.github.com/repos/realm/SwiftLint/pulls/comments/50613775"},"html":{"href":"https://github.com/realm/SwiftLint/pull/391#discussion_r50613775"},"pull_request":{"href":"https://api.github.com/repos/realm/SwiftLint/pulls/391"}}},"pull_request":{"url":"https://api.github.com/repos/realm/SwiftLint/pulls/391","id":56700493,"html_url":"https://github.com/realm/SwiftLint/pull/391","diff_url":"https://github.com/realm/SwiftLint/pull/391.diff","patch_url":"https://github.com/realm/SwiftLint/pull/391.patch","issue_url":"https://api.github.com/repos/realm/SwiftLint/issues/391","number":391,"state":"open","locked":false,"title":"Configuration Structs","user":{"login":"scottrhoyt","id":4259250,"avatar_url":"https://avatars.githubusercontent.com/u/4259250?v=3","gravatar_id":"","url":"https://api.github.com/users/scottrhoyt","html_url":"https://github.com/scottrhoyt","followers_url":"https://api.github.com/users/scottrhoyt/followers","following_url":"https://api.github.com/users/scottrhoyt/following{/other_user}","gists_url":"https://api.github.com/users/scottrhoyt/gists{/gist_id}","starred_url":"https://api.github.com/users/scottrhoyt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scottrhoyt/subscriptions","organizations_url":"https://api.github.com/users/scottrhoyt/orgs","repos_url":"https://api.github.com/users/scottrhoyt/repos","events_url":"https://api.github.com/users/scottrhoyt/events{/privacy}","received_events_url":"https://api.github.com/users/scottrhoyt/received_events","type":"User","site_admin":false},"body":"# Configuration Structs\r\n\r\nThis PR expands upon the work in #314 and #354 by providing `struct`-based configurations for the common patterns and providing default conformance to `ConfigurableRule` via these structures.\r\n\r\n## Key Benefits\r\n\r\n* All `Rule`s now have some sort of configuration available.\r\n  * Basic rules are now configurable in their violation severity. (`SeverityConfig`)\r\n  * Rules with multiple severity levels are configurable in one or both levels. (`SeverityLevelsConfig`)\r\n  * Name evaluation rules are configurable in their `min_length` and `max_length` (both `warning` and `error`) as well as with `excluded` names. (`NameConfig`)\r\n* Rule configurations can be partly or fully customized.\r\n* Performance has been increased by ~2% (vs `master`) by folding `VariableNameMinLengthRule` and `VariableNameMaxLengthRule` into `VariableNameRule`.\r\n* Test coverage has been increased.\r\n\r\n## Key Drawbacks\r\n\r\n* This introduces some additional verbosity because `ConfigProviderRule`s need to access their configuration via `config` and it's properties. This can be somewhat mitigated with more convenience computed properties.\r\n\r\n## Example YAML\r\n\r\nThe following configuration is now possible.\r\n\r\n```yaml\r\nforce_cast: Warning      # supports severity config case-insensitive\r\ntodo:\r\n  severity: error        # severity can be configure key/value as well\r\nline_length: 120         # only warning configured\r\nfile_length:\r\n  warning: 500\r\n  error: 1200\r\nfunction_body_length:    # warning and error via array still supported\r\n  - 40\r\n  - 60\r\ntype_name:\r\n  min_length: 4          # only warning\r\n  max_length:            # warning and error\r\n    warning: 40\r\n    error: 50\r\n  excluded: iPhone       # excluded via string\r\nvariable_name:\r\n  min_length:            # only min_length\r\n    error: 4             # only error\r\n  excluded:              # excluded via string array\r\n    - id\r\n    - URL\r\n    - GlobalAPIKey\r\n```\r\n## Open Issues Addressed\r\n\r\n* Closes #388\r\n* Closes #371\r\n* Closes #130\r\n* Workaround for #268 (via `severity`)\r\n* Workaround for #259 (via `excluded`)\r\n* Workaround for #191 (via `excluded`)\r\n\r\n## Design Decisions\r\n\r\n* Used `struct`s for `RuleConfig`s to encapsulate configuration via `Dictionary`s and also promote maximum reusability (e.g. `NameConfig` uses two `SeverityLevelsConfig`s).\r\n* Left `ConfigurableRule` in place as a catch-all for non-standard configs (e.g. `MissingDocsRule`)\r\n* Used `RuleConfig.setConfig(config:) throws` instead of a failable initializer for ingesting configuration dictionaries. This is to support the coexistence of default values and configured values so that partial configurations can be provided via the YAML.\r\n* Switched `ConfigurableRule.init?(config:)` to `ConfigurableRule.init(config:) throws`to gracefully propograte these `ConfigurationError`s.\r\n\r\n## TODO\r\n\r\n- [ ] Update README\r\n- [ ] Update CHANGELOG\r\n- [ ] Update CONTRIBUTING\r\n\r\n/cc @realm/swiftlint ","created_at":"2016-01-21T03:19:07Z","updated_at":"2016-01-23T02:15:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"509b428ceabf9041bc6bc9f9f7e2642700ea6d44","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/realm/SwiftLint/pulls/391/commits","review_comments_url":"https://api.github.com/repos/realm/SwiftLint/pulls/391/comments","review_comment_url":"https://api.github.com/repos/realm/SwiftLint/pulls/comments{/number}","comments_url":"https://api.github.com/repos/realm/SwiftLint/issues/391/comments","statuses_url":"https://api.github.com/repos/realm/SwiftLint/statuses/2ffab8cd356faa20eb62ef406b48589516cc4e15","head":{"label":"realm:sh-configuration-structs","ref":"sh-configuration-structs","sha":"2ffab8cd356faa20eb62ef406b48589516cc4e15","user":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"repo":{"id":35732214,"name":"SwiftLint","full_name":"realm/SwiftLint","owner":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/realm/SwiftLint","description":"A tool to enforce Swift style and conventions.","fork":false,"url":"https://api.github.com/repos/realm/SwiftLint","forks_url":"https://api.github.com/repos/realm/SwiftLint/forks","keys_url":"https://api.github.com/repos/realm/SwiftLint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/realm/SwiftLint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/realm/SwiftLint/teams","hooks_url":"https://api.github.com/repos/realm/SwiftLint/hooks","issue_events_url":"https://api.github.com/repos/realm/SwiftLint/issues/events{/number}","events_url":"https://api.github.com/repos/realm/SwiftLint/events","assignees_url":"https://api.github.com/repos/realm/SwiftLint/assignees{/user}","branches_url":"https://api.github.com/repos/realm/SwiftLint/branches{/branch}","tags_url":"https://api.github.com/repos/realm/SwiftLint/tags","blobs_url":"https://api.github.com/repos/realm/SwiftLint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/realm/SwiftLint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/realm/SwiftLint/git/refs{/sha}","trees_url":"https://api.github.com/repos/realm/SwiftLint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/realm/SwiftLint/statuses/{sha}","languages_url":"https://api.github.com/repos/realm/SwiftLint/languages","stargazers_url":"https://api.github.com/repos/realm/SwiftLint/stargazers","contributors_url":"https://api.github.com/repos/realm/SwiftLint/contributors","subscribers_url":"https://api.github.com/repos/realm/SwiftLint/subscribers","subscription_url":"https://api.github.com/repos/realm/SwiftLint/subscription","commits_url":"https://api.github.com/repos/realm/SwiftLint/commits{/sha}","git_commits_url":"https://api.github.com/repos/realm/SwiftLint/git/commits{/sha}","comments_url":"https://api.github.com/repos/realm/SwiftLint/comments{/number}","issue_comment_url":"https://api.github.com/repos/realm/SwiftLint/issues/comments{/number}","contents_url":"https://api.github.com/repos/realm/SwiftLint/contents/{+path}","compare_url":"https://api.github.com/repos/realm/SwiftLint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/realm/SwiftLint/merges","archive_url":"https://api.github.com/repos/realm/SwiftLint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/realm/SwiftLint/downloads","issues_url":"https://api.github.com/repos/realm/SwiftLint/issues{/number}","pulls_url":"https://api.github.com/repos/realm/SwiftLint/pulls{/number}","milestones_url":"https://api.github.com/repos/realm/SwiftLint/milestones{/number}","notifications_url":"https://api.github.com/repos/realm/SwiftLint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/realm/SwiftLint/labels{/name}","releases_url":"https://api.github.com/repos/realm/SwiftLint/releases{/id}","deployments_url":"https://api.github.com/repos/realm/SwiftLint/deployments","created_at":"2015-05-16T16:59:31Z","updated_at":"2016-01-22T22:10:16Z","pushed_at":"2016-01-23T02:04:26Z","git_url":"git://github.com/realm/SwiftLint.git","ssh_url":"git@github.com:realm/SwiftLint.git","clone_url":"https://github.com/realm/SwiftLint.git","svn_url":"https://github.com/realm/SwiftLint","homepage":"","size":1186,"stargazers_count":3052,"watchers_count":3052,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":175,"mirror_url":null,"open_issues_count":62,"forks":175,"open_issues":62,"watchers":3052,"default_branch":"master"}},"base":{"label":"realm:master","ref":"master","sha":"cc41abbdfa79fa53483530afdc12c0fb04562ee5","user":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"repo":{"id":35732214,"name":"SwiftLint","full_name":"realm/SwiftLint","owner":{"login":"realm","id":7575099,"avatar_url":"https://avatars.githubusercontent.com/u/7575099?v=3","gravatar_id":"","url":"https://api.github.com/users/realm","html_url":"https://github.com/realm","followers_url":"https://api.github.com/users/realm/followers","following_url":"https://api.github.com/users/realm/following{/other_user}","gists_url":"https://api.github.com/users/realm/gists{/gist_id}","starred_url":"https://api.github.com/users/realm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realm/subscriptions","organizations_url":"https://api.github.com/users/realm/orgs","repos_url":"https://api.github.com/users/realm/repos","events_url":"https://api.github.com/users/realm/events{/privacy}","received_events_url":"https://api.github.com/users/realm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/realm/SwiftLint","description":"A tool to enforce Swift style and conventions.","fork":false,"url":"https://api.github.com/repos/realm/SwiftLint","forks_url":"https://api.github.com/repos/realm/SwiftLint/forks","keys_url":"https://api.github.com/repos/realm/SwiftLint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/realm/SwiftLint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/realm/SwiftLint/teams","hooks_url":"https://api.github.com/repos/realm/SwiftLint/hooks","issue_events_url":"https://api.github.com/repos/realm/SwiftLint/issues/events{/number}","events_url":"https://api.github.com/repos/realm/SwiftLint/events","assignees_url":"https://api.github.com/repos/realm/SwiftLint/assignees{/user}","branches_url":"https://api.github.com/repos/realm/SwiftLint/branches{/branch}","tags_url":"https://api.github.com/repos/realm/SwiftLint/tags","blobs_url":"https://api.github.com/repos/realm/SwiftLint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/realm/SwiftLint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/realm/SwiftLint/git/refs{/sha}","trees_url":"https://api.github.com/repos/realm/SwiftLint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/realm/SwiftLint/statuses/{sha}","languages_url":"https://api.github.com/repos/realm/SwiftLint/languages","stargazers_url":"https://api.github.com/repos/realm/SwiftLint/stargazers","contributors_url":"https://api.github.com/repos/realm/SwiftLint/contributors","subscribers_url":"https://api.github.com/repos/realm/SwiftLint/subscribers","subscription_url":"https://api.github.com/repos/realm/SwiftLint/subscription","commits_url":"https://api.github.com/repos/realm/SwiftLint/commits{/sha}","git_commits_url":"https://api.github.com/repos/realm/SwiftLint/git/commits{/sha}","comments_url":"https://api.github.com/repos/realm/SwiftLint/comments{/number}","issue_comment_url":"https://api.github.com/repos/realm/SwiftLint/issues/comments{/number}","contents_url":"https://api.github.com/repos/realm/SwiftLint/contents/{+path}","compare_url":"https://api.github.com/repos/realm/SwiftLint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/realm/SwiftLint/merges","archive_url":"https://api.github.com/repos/realm/SwiftLint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/realm/SwiftLint/downloads","issues_url":"https://api.github.com/repos/realm/SwiftLint/issues{/number}","pulls_url":"https://api.github.com/repos/realm/SwiftLint/pulls{/number}","milestones_url":"https://api.github.com/repos/realm/SwiftLint/milestones{/number}","notifications_url":"https://api.github.com/repos/realm/SwiftLint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/realm/SwiftLint/labels{/name}","releases_url":"https://api.github.com/repos/realm/SwiftLint/releases{/id}","deployments_url":"https://api.github.com/repos/realm/SwiftLint/deployments","created_at":"2015-05-16T16:59:31Z","updated_at":"2016-01-22T22:10:16Z","pushed_at":"2016-01-23T02:04:26Z","git_url":"git://github.com/realm/SwiftLint.git","ssh_url":"git@github.com:realm/SwiftLint.git","clone_url":"https://github.com/realm/SwiftLint.git","svn_url":"https://github.com/realm/SwiftLint","homepage":"","size":1186,"stargazers_count":3052,"watchers_count":3052,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":175,"mirror_url":null,"open_issues_count":62,"forks":175,"open_issues":62,"watchers":3052,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/realm/SwiftLint/pulls/391"},"html":{"href":"https://github.com/realm/SwiftLint/pull/391"},"issue":{"href":"https://api.github.com/repos/realm/SwiftLint/issues/391"},"comments":{"href":"https://api.github.com/repos/realm/SwiftLint/issues/391/comments"},"review_comments":{"href":"https://api.github.com/repos/realm/SwiftLint/pulls/391/comments"},"review_comment":{"href":"https://api.github.com/repos/realm/SwiftLint/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/realm/SwiftLint/pulls/391/commits"},"statuses":{"href":"https://api.github.com/repos/realm/SwiftLint/statuses/2ffab8cd356faa20eb62ef406b48589516cc4e15"}}}}