diff --git a/Package.swift b/Package.swift index 996d7b5..2fca0db 100644 --- a/Package.swift +++ b/Package.swift @@ -33,6 +33,7 @@ let package = Package( .target( name: "Core", dependencies: [ + .product(name: "BetterCodable", package: "BetterCodable"), .product(name: "Rainbow", package: "Rainbow"), ] ), diff --git a/README.md b/README.md index 0b5b714..ca413c0 100644 --- a/README.md +++ b/README.md @@ -83,34 +83,48 @@ This will create the Swift script file `anylint.yml` with something like the fol ```yaml FileContents: [] -# - id: Readme -# hint: 'Each project should have a README.md file, explaining how to use or contribute to the project.' -# regex: '^README\.md$' -# violateIfNoMatchesFound: true -# matchingExamples: ['README.md'] -# nonMatchingExamples: ['README.markdown', 'Readme.md', 'ReadMe.md'] +# TODO: replace below sample checks with your custom checks and remove empty array specifier `[]` from above + # - id: ReadmeTypoLicense + # hint: 'ReadmeTypoLicense: Misspelled word `license`.' + # regex: '([\s#]L|l)isence([\s\.,:;])' + # matchingExamples: [' lisence:', "## Lisence\n"] + # nonMatchingExamples: [' license:', "## License\n"] + # includeFilters: ['^README\.md$'] + # autoCorrectReplacement: '$1icense$2' + # autoCorrectExamples: + # - { before: ' lisence:', after: ' license:' } + # - { before: "## Lisence\n", after: "## License\n" } FilePaths: [] -# - id: 'ReadmePath' -# hint: 'The README file should be named exactly `README.md`.' -# regex: '^(.*/)?([Rr][Ee][Aa][Dd][Mm][Ee]\.markdown|readme\.md|Readme\.md|ReadMe\.md)$' -# matchingExamples: ['README.markdown', 'readme.md', 'ReadMe.md'] -# nonMatchingExamples: ['README.md', 'CHANGELOG.md', 'CONTRIBUTING.md', 'api/help.md'] -# autoCorrectReplacement: '$1README.md' -# autoCorrectExamples: -# - { before: 'api/readme.md', after: 'api/README.md' } -# - { before: 'ReadMe.md', after: 'README.md' } -# - { before: 'README.markdown', after: 'README.md' } +# TODO: replace below sample checks with your custom checks and remove empty array specifier `[]` from above + # - id: Readme + # hint: 'Each project should have a README.md file, explaining how to use or contribute to the project.' + # regex: '^README\.md$' + # violateIfNoMatchesFound: true + # matchingExamples: ['README.md'] + # nonMatchingExamples: ['README.markdown', 'Readme.md', 'ReadMe.md'] + # + # - id: ReadmePath + # hint: 'The README file should be named exactly `README.md`.' + # regex: '^(.*/)?([Rr][Ee][Aa][Dd][Mm][Ee]\.markdown|readme\.md|Readme\.md|ReadMe\.md)$' + # matchingExamples: ['README.markdown', 'readme.md', 'ReadMe.md'] + # nonMatchingExamples: ['README.md', 'CHANGELOG.md', 'CONTRIBUTING.md', 'api/help.md'] + # autoCorrectReplacement: '$1README.md' + # autoCorrectExamples: + # - { before: 'api/readme.md', after: 'api/README.md' } + # - { before: 'ReadMe.md', after: 'README.md' } + # - { before: 'README.markdown', after: 'README.md' } CustomScripts: [] -# - id: LintConfig -# hint: 'Lint the AnyLint config file to conform to YAML best practices.' -# command: |- -# if which yamllint > /dev/null; then -# yamllint anylint.yml -# else -# echo '{ "warning": { "YamlLint: Not installed, see instructions at https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint": [{}] } }' -# fi +# TODO: replace below sample check with your custom checks and remove empty array specifier `[]` from above + # - id: LintConfig + # hint: 'Lint the AnyLint config file to conform to YAML best practices.' + # command: |- + # if which yamllint > /dev/null; then + # yamllint anylint.yml + # else + # echo '{ "warning": { "YamlLint@warning: Not installed, see instructions at https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint": [{}] } }' + # fi ``` diff --git a/Sources/Checkers/Lint.swift b/Sources/Checkers/Lint.swift index ce9644a..58206d4 100644 --- a/Sources/Checkers/Lint.swift +++ b/Sources/Checkers/Lint.swift @@ -137,6 +137,7 @@ public enum Lint { public static func runCustomScript(check: Check, command: String) throws -> LintResults { let tempScriptFileUrl = URL(fileURLWithPath: "_\(check.id).tempscript") try command.write(to: tempScriptFileUrl, atomically: true, encoding: .utf8) + try shellOut(to: "chmod", arguments: ["+x", tempScriptFileUrl.path]) do { let output = try shellOut(to: "/bin/bash", arguments: [tempScriptFileUrl.path]) diff --git a/Sources/Configuration/Core+DefaultCodableStrategy.swift b/Sources/Configuration/Core+DefaultCodableStrategy.swift index 65c96c8..aea7e58 100644 --- a/Sources/Configuration/Core+DefaultCodableStrategy.swift +++ b/Sources/Configuration/Core+DefaultCodableStrategy.swift @@ -10,6 +10,7 @@ extension Severity { } extension Regex { + /// Use to set the default value of `Regex` instances to `.*` in rules when users don't provide an explicit value. public enum DefaultToMatchAllArray: DefaultCodableStrategy { public static var defaultValue: [Regex] { [try! Regex(".*")] } } diff --git a/Sources/Configuration/Templates/Blank.yml b/Sources/Configuration/Templates/Blank.yml index 9d9bddf..8f5cab2 100644 --- a/Sources/Configuration/Templates/Blank.yml +++ b/Sources/Configuration/Templates/Blank.yml @@ -60,5 +60,5 @@ CustomScripts: [] # if which yamllint > /dev/null; then # yamllint anylint.yml # else - # echo '{ "warning": { "YamlLint: Not installed, see instructions at https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint": [{}] } }' + # echo '{ "warning": { "YamlLint@warning: Not installed, see instructions at https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint": [{}] } }' # fi diff --git a/Sources/Configuration/Templates/OpenSource.yml b/Sources/Configuration/Templates/OpenSource.yml index 8f7f88d..3fb7dfe 100644 --- a/Sources/Configuration/Templates/OpenSource.yml +++ b/Sources/Configuration/Templates/OpenSource.yml @@ -57,5 +57,5 @@ CustomScripts: if which yamllint > /dev/null; then yamllint anylint.yml else - echo '{ "warning": { "YamlLint: Not installed, see instructions at https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint": [{}] } }' + echo '{ "warning": { "YamlLint@warning: Not installed, see instructions at https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint": [{}] } }' fi diff --git a/Sources/Core/Extensions/Date+DefaultCodableStrategy.swift b/Sources/Core/Extensions/Date+DefaultCodableStrategy.swift new file mode 100644 index 0000000..d72aedd --- /dev/null +++ b/Sources/Core/Extensions/Date+DefaultCodableStrategy.swift @@ -0,0 +1,9 @@ +import Foundation +import BetterCodable + +extension Date { + /// Use to set the default value of `Date` instances to `Date.now` in rules when users don't provide an explicit value. + public enum DefaultToNow: DefaultCodableStrategy { + public static var defaultValue: Date { Date() } + } +} diff --git a/Sources/Core/Violation.swift b/Sources/Core/Violation.swift index b585a59..f0d3d8b 100644 --- a/Sources/Core/Violation.swift +++ b/Sources/Core/Violation.swift @@ -1,9 +1,11 @@ import Foundation +import BetterCodable /// A violation found in a check. public struct Violation: Codable, Equatable { /// The exact time this violation was discovered. Needed for sorting purposes. - public let discoverDate: Date + @DefaultCodable + public var discoverDate: Date /// The matched string that violates the check. public let matchedString: String?