diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100755 index 0000000..45ddbb5 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,60 @@ +version: 2.1 + +orbs: + codacy: codacy/base@12.2.0 + codacy_plugins_test: codacy/plugins-test@2.0.11 + +workflows: + compile_test_deploy: + jobs: + - codacy/checkout_and_version: + write_sbt_version: true + - codacy/sbt_docker: + name: publish_docker_local + steps: + - run: + name: Check Scalafmt on sources + command: sbt scalafmtCheckAll + - run: + name: Check Scalafmt on Sbt sources + command: sbt scalafmtSbtCheck + - run: + name: Build DEV java tool + command: sbt stage + - run: + name: Build Documentation generator + command: sbt doc-generator/stage + - run: + name: Build DEV image (runs doc-generator) + command: docker build -t codacy-swiftlint-dev -f Dockerfile.dev . + - run: + name: Build Graalvm native-image + command: sbt nativeImage + - run: + name: Build release Docker image + command: docker build -t $CIRCLE_PROJECT_REPONAME:latest . + - run: + name: Save Docker image to workspace + command: docker save --output docker-image.tar $CIRCLE_PROJECT_REPONAME:latest + persist_to_workspace: true + cache_prefix: sbt-cache-09012023 + requires: + - codacy/checkout_and_version + - codacy_plugins_test/run: + name: plugins_test + run_multiple_tests: true + requires: + - publish_docker_local + - codacy/publish_docker: + context: CodacyDocker + requires: + - plugins_test + filters: + branches: + only: + - master + - codacy/tag_version: + name: tag_version + context: CodacyAWS + requires: + - codacy/publish_docker diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..07ff5c6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +# Ignore everything +** + +# Allow files and directories +!target/native-image/codacy-swiftlint +!/target/universal/stage/ +!/doc-generator/target/universal/stage/ +!/docs + +# Ignore unnecessary files inside allowed directories +# This should go after the allowed directories +**/.DS_Store diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..30f4c10 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @codacy/toss diff --git a/.github/workflows/comment_issue.yml b/.github/workflows/comment_issue.yml new file mode 100644 index 0000000..12fb218 --- /dev/null +++ b/.github/workflows/comment_issue.yml @@ -0,0 +1,97 @@ +name: Comment issue on Jira + +on: + issue_comment: + types: [created] + +jobs: + jira: + env: + JIRA_CREATE_COMMENT_AUTO: ${{ secrets.JIRA_CREATE_COMMENT_AUTO }} + runs-on: ubuntu-latest + steps: + + - name: Start workflow if JIRA_CREATE_COMMENT_AUTO is enabled + if: env.JIRA_CREATE_COMMENT_AUTO == 'true' + run: echo "Starting workflow" + + - name: Check GitHub Issue type + if: env.JIRA_CREATE_COMMENT_AUTO == 'true' + id: github_issue_type + uses: actions/github-script@v2.0.0 + with: + result-encoding: string + script: | + // An Issue can be a pull request, you can identify pull requests by the pull_request key + const pullRequest = ${{ toJson(github.event.issue.pull_request) }} + if(pullRequest) { + return "pull-request" + } else { + return "issue" + } + + - name: Check if GitHub Issue has JIRA_ISSUE_LABEL + if: env.JIRA_CREATE_COMMENT_AUTO == 'true' + id: github_issue_has_jira_issue_label + uses: actions/github-script@v2.0.0 + env: + JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }} + with: + result-encoding: string + script: | + const labels = ${{ toJson(github.event.issue.labels) }} + if(labels.find(label => label.name == process.env.JIRA_ISSUE_LABEL)) { + return "true" + } else { + return "false" + } + + - name: Continue workflow only for Issues (not Pull Requests) tagged with JIRA_ISSUE_LABEL + if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' + env: + GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} + GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} + run: echo "GitHub Issue is tracked on Jira, eligilbe to be commented" + + - name: Jira Login + if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' + id: login + uses: atlassian/gajira-login@v2.0.0 + env: + GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} + GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Extract Jira number + if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' + id: extract_jira_number + uses: actions/github-script@v2.0.0 + env: + GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} + GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} + JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }} + GITHUB_TITLE: ${{ github.event.issue.title }} + with: + script: | + const jiraTaskRegex = new RegExp(`\\\[(${process.env.JIRA_PROJECT}-[0-9]+?)\\\]`) + return process.env.GITHUB_TITLE.match(jiraTaskRegex)[1] + result-encoding: string + + - name: Jira Add comment on issue + if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' + id: add_comment_jira_issue + uses: atlassian/gajira-comment@v2.0.2 + env: + GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} + GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} + with: + issue: ${{ steps.extract_jira_number.outputs.result }} + comment: | + GitHub Comment : ${{ github.event.comment.user.login }} + {quote}${{ github.event.comment.body }}{quote} + ---- + {panel} + _[Github permalink |${{ github.event.comment.html_url }}]_ + {panel} diff --git a/.github/workflows/create_issue.yml b/.github/workflows/create_issue.yml new file mode 100644 index 0000000..14c9f3b --- /dev/null +++ b/.github/workflows/create_issue.yml @@ -0,0 +1,90 @@ +name: Create issue on Jira + +on: + issues: + types: [opened] + +jobs: + jira: + env: + JIRA_CREATE_ISSUE_AUTO: ${{ secrets.JIRA_CREATE_ISSUE_AUTO }} + runs-on: ubuntu-latest + steps: + + - name: Start workflow if JIRA_CREATE_ISSUE_AUTO is enabled + if: env.JIRA_CREATE_ISSUE_AUTO == 'true' + run: echo "Starting workflow" + + - name: Jira Login + if: env.JIRA_CREATE_ISSUE_AUTO == 'true' + id: login + uses: atlassian/gajira-login@v2.0.0 + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Jira Create issue + if: env.JIRA_CREATE_ISSUE_AUTO == 'true' + id: create_jira_issue + uses: atlassian/gajira-create@v2.0.1 + with: + project: ${{ secrets.JIRA_PROJECT }} + issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} + summary: "[GH#${{ github.event.issue.number }}] ${{ github.event.issue.title }}" + description: | + ${{ github.event.issue.body }} + ---- + {panel} + _[Github permalink |${{ github.event.issue.html_url }}]_ + {panel} + + - name: Update Jira issue if JIRA_UPDATE_ISSUE_BODY is defined + if: env.JIRA_CREATE_ISSUE_AUTO == 'true' && env.JIRA_UPDATE_ISSUE_BODY != '' + env: + JIRA_UPDATE_ISSUE_BODY: ${{ secrets.JIRA_UPDATE_ISSUE_BODY }} + run: > + curl + -u ${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }} + -X PUT + -H 'Content-Type: application/json' + -d '${{ env.JIRA_UPDATE_ISSUE_BODY }}' + ${{ secrets.JIRA_BASE_URL }}/rest/api/2/issue/${{ steps.create_jira_issue.outputs.issue }} + + - name: Update GitHub issue + if: env.JIRA_CREATE_ISSUE_AUTO == 'true' + uses: actions/github-script@v2.0.0 + env: + JIRA_ISSUE_NUMBER: ${{ steps.create_jira_issue.outputs.issue }} + GITHUB_ORIGINAL_TITLE: ${{ github.event.issue.title }} + JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }} + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const newTitle = `[${process.env.JIRA_ISSUE_NUMBER}] ${process.env.GITHUB_ORIGINAL_TITLE}` + github.issues.update({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + title: newTitle + }) + github.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: [process.env.JIRA_ISSUE_LABEL] + }) + + + - name: Add comment after sync + if: env.JIRA_CREATE_ISSUE_AUTO == 'true' + uses: actions/github-script@v2.0.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Internal ticket created : [${{ steps.create_jira_issue.outputs.issue }}](${{ secrets.JIRA_BASE_URL }}/browse/${{ steps.create_jira_issue.outputs.issue }})' + }) diff --git a/.github/workflows/create_issue_on_label.yml b/.github/workflows/create_issue_on_label.yml new file mode 100644 index 0000000..de4ab93 --- /dev/null +++ b/.github/workflows/create_issue_on_label.yml @@ -0,0 +1,82 @@ +name: Create issue on Jira when labeled with JIRA_ISSUE_LABEL + +on: + issues: + types: [labeled] + +jobs: + jira: + env: + JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }} + runs-on: ubuntu-latest + steps: + + - name: Start workflow if GitHub issue is tagged with JIRA_ISSUE_LABEL + if: github.event.label.name == env.JIRA_ISSUE_LABEL + run: echo "Starting workflow" + + - name: Jira Login + if: github.event.label.name == env.JIRA_ISSUE_LABEL + id: login + uses: atlassian/gajira-login@v2.0.0 + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Jira Create issue + if: github.event.label.name == env.JIRA_ISSUE_LABEL + id: create_jira_issue + uses: atlassian/gajira-create@v2.0.1 + with: + project: ${{ secrets.JIRA_PROJECT }} + issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} + summary: "[GH#${{ github.event.issue.number }}] ${{ github.event.issue.title }}" + description: | + ${{ github.event.issue.body }} + ---- + {panel} + _[Github permalink |${{ github.event.issue.html_url }}]_ + {panel} + + - name: Update Jira issue if JIRA_UPDATE_ISSUE_BODY is defined + if: github.event.label.name == env.JIRA_ISSUE_LABEL && env.JIRA_UPDATE_ISSUE_BODY != '' + env: + JIRA_UPDATE_ISSUE_BODY: ${{ secrets.JIRA_UPDATE_ISSUE_BODY }} + run: > + curl + -u ${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }} + -X PUT + -H 'Content-Type: application/json' + -d '${{ env.JIRA_UPDATE_ISSUE_BODY }}' + ${{ secrets.JIRA_BASE_URL }}/rest/api/2/issue/${{ steps.create_jira_issue.outputs.issue }} + + - name: Change Title + if: github.event.label.name == env.JIRA_ISSUE_LABEL + uses: actions/github-script@v2.0.0 + env: + JIRA_ISSUE_NUMBER: ${{ steps.create_jira_issue.outputs.issue }} + GITHUB_ORIGINAL_TITLE: ${{ github.event.issue.title }} + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const newTitle = `[${process.env.JIRA_ISSUE_NUMBER}] ${process.env.GITHUB_ORIGINAL_TITLE}` + github.issues.update({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + title: newTitle + }) + + - name: Add comment after sync + if: github.event.label.name == env.JIRA_ISSUE_LABEL + uses: actions/github-script@v2.0.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Internal ticket created : [${{ steps.create_jira_issue.outputs.issue }}](${{ secrets.JIRA_BASE_URL }}/browse/${{ steps.create_jira_issue.outputs.issue }})' + }) diff --git a/.gitignore b/.gitignore index 0a93913..b4b61c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ -/RUNNING_PID -/logs/ -/project/*-shim.sbt -/project/project/ -/project/target/ -/target/ +target .idea .DS_Store +.metals +.bloop +.vscode +.bsp +metals.sbt + +#Ignore vscode AI rules +.github/copilot-instructions.md diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..df338e7 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,24 @@ +version = "1.5.1" +style = IntelliJ + +align = none +assumeStandardLibraryStripMargin = false +binPack.literalArgumentLists = true +binPack.parentConstructors = false +continuationIndent.defnSite = 4 +danglingParentheses = true +docstrings = ScalaDoc +includeCurlyBraceInSelectChains = true +lineEndings = unix +maxColumn = 120 +newlines.alwaysBeforeTopLevelStatements = true +newlines.penalizeSingleSelectMultiArgList = false +newlines.sometimesBeforeColonInMethodReturnType = true +optIn.breakChainOnFirstMethodDot = true +project.git = true +rewrite.rules = [ SortImports, PreferCurlyFors ] +spaces.afterKeywordBeforeParen = true + +project.includeFilters = [".*\\.sbt$", ".*\\.scala$"] +project.excludeFilters = [".*\\.scala.html$", "target/.*", "modules/admin/target/.*"] +onTestFailure = "To fix this, run `scalafmt` within sbt or `sbt scalafmt` on the project base directory" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f88f25d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM codacy-swiftlint-dev as builder + +FROM ghcr.io/realm/swiftlint:0.59.1 + +COPY --from=builder /docs /docs +COPY target/native-image/codacy-swiftlint /workdir/ +RUN apt-get update && apt-get install -y adduser +RUN adduser --uid 2004 --disabled-password docker +USER docker +WORKDIR /src +ENTRYPOINT ["/workdir/codacy-swiftlint"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..7214a79 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,13 @@ +FROM norionomura/swiftlint:0.59.1_swift-6.1 + +RUN apt-get update && apt-get install -y openjdk-17-jre-headless + +COPY docs /docs +COPY target/universal/stage/ /workdir/ +COPY doc-generator/target/universal/stage/ /doc-generator +RUN (cd workdir && /doc-generator/bin/doc-generator) +RUN chmod +x /workdir/bin/codacy-swiftlint +RUN adduser --uid 2004 --disabled-password --gecos "" docker +USER docker +WORKDIR /src +ENTRYPOINT ["/workdir/bin/codacy-swiftlint"] diff --git a/README.md b/README.md index 0af3f87..8fdf593 100755 --- a/README.md +++ b/README.md @@ -1,33 +1,52 @@ -[![Build Status](https://circleci.com/gh/fnxpt/codacy-swiftlint.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/fnxpt/codacy-swiftlint) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/c19f9b18251e4dc5bce89b0a70d0bc70)](https://app.codacy.com/gh/codacy/codacy-swiftlint?utm_source=github.com&utm_medium=referral&utm_content=codacy/codacy-swiftlint&utm_campaign=Badge_Grade_Settings) +[![Build Status](https://circleci.com/gh/codacy/codacy-swiftlint.svg?style=svg)](https://circleci.com/gh/codacy/codacy-swiftlint) # Codacy Swiftlint This is the docker engine we use at Codacy to have [Swiftlint](https://github.com/realm/SwiftLint) support. You can also create a docker to integrate the tool and language of your choice! -Check the **Docs** section for more information. +See the [codacy-engine-scala-seed](https://github.com/codacy/codacy-engine-scala-seed) repository for more information. ## Usage -You can create the docker by doing: +You need to create the DEV image: +```bash +sbt stage +docker build -t codacy-swiftlint-dev -f Dockerfile.dev . ``` -sbt docker:publishLocal + +then you can create the docker by doing: +**note** The works only on Linux for now, for local test use the DEV image + +```bash +sbt nativeImage +docker build -t codacy-swiftlint . ``` The docker is ran with the following command: -``` +```bash docker run -it -v $srcDir:/src : ``` -## Docs +## Generate docs +Build the DEV image and then run: +``` +CONTAINER=$(docker run -d --entrypoint sh -it --rm codacy-swiftlint-dev) +docker cp $CONTAINER:/docs . +docker kill $CONTAINER +``` -[Tool Developer Guide](https://support.codacy.com/hc/en-us/articles/207994725-Tool-Developer-Guide) +## Test -[Tool Developer Guide - Using Scala](https://support.codacy.com/hc/en-us/articles/207280379-Tool-Developer-Guide-Using-Scala) +For a faster development loop you can create a Docker image based on the JVM instead of creating a native-image: -## Test +```bash +sbt universal:stage +docker build -t codacy-swiftlint-dev -f Dockerfile.dev . +``` We use the [codacy-plugins-test](https://github.com/codacy/codacy-plugins-test) to test our external tools integration. You can follow the instructions there to make sure your tool is working as expected. diff --git a/build.sbt b/build.sbt index e2e92d7..e337e4b 100755 --- a/build.sbt +++ b/build.sbt @@ -1,65 +1,27 @@ -import com.typesafe.sbt.packager.docker.{Cmd, ExecCmd} - -name := """codacy-swiftlint""" +organization := "com.codacy" -version := "1.0.0-SNAPSHOT" +name := "codacy-swiftlint" -val languageVersion = "2.11.11" +ThisBuild / scalaVersion := "2.13.16" -scalaVersion := languageVersion +enablePlugins(NativeImagePlugin) -resolvers ++= Seq( - "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/releases", - "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/" -) +enablePlugins(JavaAppPackaging) libraryDependencies ++= Seq( - "com.typesafe.play" %% "play-json" % "2.4.8", - "com.codacy" %% "codacy-engine-scala-seed" % "2.7.9" withSources() + "com.codacy" %% "codacy-engine-scala-seed" % "6.1.5", + "com.github.pathikrit" %% "better-files" % "3.9.2" ) -enablePlugins(JavaAppPackaging) - -enablePlugins(DockerPlugin) - -version in Docker := "1.0.0-SNAPSHOT" - -organization := "com.codacy" - -val swiftlintVersion = "0.23.1" - -val installAll = - s"""apt-get update && - |apt-get install default-jre --assume-yes""".stripMargin.replaceAll(System.lineSeparator(), " ") - -mappings in Universal <++= (resourceDirectory in Compile) map { (resourceDir: File) => - val src = resourceDir / "docs" - val dest = "/docs" - - for { - path <- (src ***).get - if !path.isDirectory - } yield path -> path.toString.replaceFirst(src.toString, dest) -} - +Compile / mainClass := Some("codacy.Engine") -val dockerUser = "docker" -val dockerGroup = "docker" +nativeImageOptions ++= Seq("-O1", "-H:+ReportExceptionStackTraces", "--no-fallback", "--no-server") -daemonUser in Docker := dockerUser - -daemonGroup in Docker := dockerGroup - -dockerBaseImage := "mkujalowicz/swiftlint:0.23.0" - -dockerCommands := dockerCommands.value.flatMap { - case cmd@Cmd("WORKDIR", _) => List(cmd, - Cmd("RUN", installAll) - ) - case cmd@(Cmd("ADD", "opt /opt")) => List(cmd, - Cmd("RUN", "mv /opt/docker/docs /docs"), - Cmd("RUN", s"""adduser --uid 2004 --disabled-password --gecos \"\" $dockerUser"""), - ExecCmd("RUN", Seq("chown", "-R", s"$dockerUser:$dockerGroup", "/docs"): _*) +lazy val `doc-generator` = project + .settings( + libraryDependencies ++= Seq( + "com.codacy" %% "codacy-engine-scala-seed" % "6.1.5", + "com.lihaoyi" %% "os-lib" % "0.10.0" + ) ) - case other => List(other) -} + .enablePlugins(JavaAppPackaging) diff --git a/circle.yml b/circle.yml deleted file mode 100755 index ef184e9..0000000 --- a/circle.yml +++ /dev/null @@ -1,42 +0,0 @@ -machine: - pre: - - echo 'DOCKER_OPTS="-s btrfs -e lxc -D --userland-proxy=false"' | sudo tee -a /etc/default/docker - - sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.0-circleci-cp-workaround' - - sudo chmod 0755 /usr/bin/docker - - mkdir -p $HOME/.sbt/.lib/0.13.13 && wget https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.13.13/sbt-launch.jar -O $HOME/.sbt/.lib/0.13.13/sbt-launch.jar - - (cd $HOME; rm -f codacy-plugins-test; git clone https://github.com/codacy/codacy-plugins-test.git) - java: - version: oraclejdk8 - services: - - docker - -dependencies: - override: - - (cd $HOME/codacy-plugins-test && sbt compile) - - (cd $HOME/$CIRCLE_PROJECT_REPONAME && sbt "set version in Docker := \"latest\"" "set name := \"$CIRCLE_PROJECT_REPONAME\"" docker:publishLocal) - cache_directories: - - "~/.ivy2" - - "~/.m2" - - "~/.sbt" - - "~/codacy-plugins-test/target" - - "~/codacy-plugins-test/project/target" - - "~/codacy-plugins-test/project/project" - - "~/$CIRCLE_PROJECT_REPONAME/target" - - "~/$CIRCLE_PROJECT_REPONAME/project/target" - - "~/$CIRCLE_PROJECT_REPONAME/project/project" - -test: - pre: - - (cd $HOME/codacy-plugins-test; git fetch --all; git reset --hard origin/master) - override: - - (cd $HOME/codacy-plugins-test && sbt -Dcodacy.tests.ignore.descriptions=true "run-main codacy.plugins.DockerTest json $CIRCLE_PROJECT_REPONAME:latest") - - (cd $HOME/codacy-plugins-test && sbt -Dcodacy.tests.noremove=true -Dcodacy.tests.threads=8 "run-main codacy.plugins.DockerTest pattern $CIRCLE_PROJECT_REPONAME:latest") - -deployment: - hub: - branch: master - commands: - - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS - - docker tag $CIRCLE_PROJECT_REPONAME codacy/$CIRCLE_PROJECT_REPONAME - - docker tag $CIRCLE_PROJECT_REPONAME codacy/$CIRCLE_PROJECT_REPONAME:1.0.$CIRCLE_BUILD_NUM - - docker push codacy/$CIRCLE_PROJECT_REPONAME diff --git a/doc-generator/src/main/scala/doc-generator.scala b/doc-generator/src/main/scala/doc-generator.scala new file mode 100644 index 0000000..b6db3cb --- /dev/null +++ b/doc-generator/src/main/scala/doc-generator.scala @@ -0,0 +1,112 @@ +import com.codacy.plugins.api._ +import com.codacy.plugins.api.results._ +import play.api.libs.json.Json + +import scala.util.control.Breaks.break + +object Main extends App { + val tempDir = os.temp.dir() + + os.proc("swiftlint", "generate-docs").call(cwd = tempDir) + + println("Generated docs using swiftlint generate-docs") + + val rulesOutput = + os.proc("swiftlint", "rules", "-v").call().out.lines().map(_.split('|').map(_.trim).toList.tail).tail + + val version = os.proc("swiftlint", "version").call().out.text().trim + + val excludeList = Set("Rule Directory.md", "Swift Syntax Dashboard.md") + + val mdFiles = os.list(tempDir / "rule_docs").filterNot(file => excludeList.contains(file.last)) + + val docsDirectory = os.root / "docs" + val descriptionDirectory = docsDirectory / "description" + + val patternDescriptions = mdFiles.map { file => + println(s"Generating patterns description from ${file.last}") + val patternId = file.last.stripSuffix(".md") + val lines = os.read(file).linesIterator + val title = lines.next().stripPrefix("# ") + lines.next() + var description = lines.next() + + val maxLength = 500 + // Keep truncating the description while it's longer than maxLength + while (description.length > maxLength) { + + val cutoffPoint = description.substring(0, maxLength).lastIndexOf(".") + + if (cutoffPoint == -1) { + description = description.substring(0, maxLength) + println("No period found within the limit. Truncating to maxLength.") + break + } else { + description = description.substring(0, cutoffPoint + 1) + } + } + Pattern.Description(Pattern.Id(patternId), Pattern.Title(title), Some(Pattern.DescriptionText(description)), None) + } + + val ids = rulesOutput.head.zipWithIndex.toMap + + case class SwiftlintRule( + identifier: String, + correctable: Boolean, + enabledInYourConfig: Boolean, + kind: String, + configuration: String + ) + + val swiftLintRules = rulesOutput.tail + .filter(_.length > 0) + .map { arr => + def toBoolean(s: String) = s == "yes" + SwiftlintRule( + identifier = arr(ids("identifier")), + correctable = toBoolean(arr(ids("correctable"))), + enabledInYourConfig = toBoolean(arr(ids("enabled in your config"))), + kind = arr(ids("kind")), + configuration = arr(ids("configuration")) + ) + } + + def configurationToLevel(kind: String) = + Option(kind) + .collectFirst { + case s if s.startsWith("severity: error") => Result.Level.Err + case s if s.startsWith("severity: warning") => Result.Level.Warn + } + .getOrElse(Result.Level.Warn) + + def kindToCategory(kind: String) = kind match { + case "style" => Pattern.Category.CodeStyle + case "lint" => Pattern.Category.ErrorProne + case "performance" => Pattern.Category.Performance + case "metrics" => Pattern.Category.Complexity + case _ => Pattern.Category.ErrorProne + } + + val patternSpecifications = swiftLintRules.map { swiftLintRule => + println(s"Generating patterns specification for ${swiftLintRule.identifier}") + println( + s"Converting severity ${swiftLintRule.configuration} => ${configurationToLevel(swiftLintRule.configuration)}" + ) + Pattern.Specification( + Pattern.Id(swiftLintRule.identifier), + configurationToLevel(swiftLintRule.configuration), + kindToCategory(swiftLintRule.kind), + subcategory = None, + enabled = swiftLintRule.enabledInYourConfig + ) + } + + val specification = + Tool.Specification(Tool.Name("swiftlint"), Some(Tool.Version(version)), patternSpecifications.toSet) + + os.write.over(docsDirectory / "patterns.json", Json.prettyPrint(Json.toJson(specification)) + "\n") + os.remove.all(descriptionDirectory) + mdFiles.foreach(os.copy.into(_, descriptionDirectory, replaceExisting = true, createFolders = true)) + os.write.over(descriptionDirectory / "description.json", Json.prettyPrint(Json.toJson(patternDescriptions)) + "\n") + os.remove.all(tempDir) +} diff --git a/docs/description/accessibility_label_for_image.md b/docs/description/accessibility_label_for_image.md new file mode 100644 index 0000000..39d7822 --- /dev/null +++ b/docs/description/accessibility_label_for_image.md @@ -0,0 +1,324 @@ +# Accessibility Label for Image + +Images that provide context should have an accessibility label or should be explicitly hidden from accessibility + +* **Identifier:** `accessibility_label_for_image` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.1.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Rationale + +In UIKit, a `UIImageView` was by default not an accessibility element, and would only be visible to VoiceOver and other assistive technologies if the developer explicitly made them an accessibility element. In SwiftUI, however, an `Image` is an accessibility element by default. If the developer does not explicitly hide them from accessibility or give them an accessibility label, they will inherit the name of the image file, which often creates a poor experience when VoiceOver reads things like "close icon white". + +Known false negatives for Images declared as instance variables and containers that provide a label but are not accessibility elements. Known false positives for Images created in a separate function from where they have accessibility properties applied. + +## Non Triggering Examples + +```swift +struct MyView: View { + var body: some View { + Image(decorative: "my-image") + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image("my-image", label: Text("Alt text for my image")) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image("my-image") + .accessibility(hidden: true) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image("my-image") + .accessibilityHidden(true) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image("my-image") + .accessibility(label: Text("Alt text for my image")) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image("my-image") + .accessibilityLabel(Text("Alt text for my image")) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image(uiImage: myUiImage) + .renderingMode(.template) + .foregroundColor(.blue) + .accessibilityHidden(true) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image(uiImage: myUiImage) + .accessibilityLabel(Text("Alt text for my image")) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + SwiftUI.Image(uiImage: "my-image").resizable().accessibilityHidden(true) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + VStack { + Image(decorative: "my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Image("my-image") + .accessibility(label: Text("Alt text for my image")) + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + VStack { + Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Image("my-image") + .accessibility(label: Text("Alt text for my image")) + }.accessibilityElement() + } +} +``` + +```swift +struct MyView: View { + var body: some View { + VStack { + Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Image("my-image") + .accessibility(label: Text("Alt text for my image")) + }.accessibilityHidden(true) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + HStack(spacing: 8) { + Image(decorative: "my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Text("Text to accompany my image") + }.accessibilityElement(children: .combine) + .padding(16) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + HStack(spacing: 8) { + Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Text("Text to accompany my image") + }.accessibilityElement(children: .ignore) + .padding(16) + .accessibilityLabel(Text("Label for my image and text")) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Button(action: { doAction() }) { + Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + } + .accessibilityLabel(Text("Label for my image")) + } +} +``` + +## Triggering Examples + +```swift +struct MyView: View { + var body: some View { + ↓Image("my-image") + .resizable(true) + .frame(width: 48, height: 48) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Image(uiImage: myUiImage) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓SwiftUI.Image(uiImage: "my-image").resizable().accessibilityHidden(false) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image(uiImage: myUiImage) + .resizable() + .frame(width: 48, height: 48) + .accessibilityLabel(Text("Alt text for my image")) + ↓Image("other image") + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Image(decorative: "image1") + ↓Image("image2") + Image(uiImage: "image3") + .accessibility(label: Text("a pretty picture")) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + VStack { + Image(decorative: "my-image") + .renderingMode(.template) + .foregroundColor(.blue) + ↓Image("my-image") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + VStack { + ↓Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Image("my-image") + .accessibility(label: Text("Alt text for my image")) + }.accessibilityElement(children: .contain) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + VStack { + ↓Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Image("my-image") + .accessibility(label: Text("Alt text for my image")) + }.accessibilityHidden(false) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + HStack(spacing: 8) { + ↓Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + Text("Text to accompany my image") + }.accessibilityElement(children: .combine) + .padding(16) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Button(action: { doAction() }) { + ↓Image("my-image") + .renderingMode(.template) + .foregroundColor(.blue) + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Image(systemName: "circle.plus") + } +} +``` \ No newline at end of file diff --git a/docs/description/accessibility_trait_for_button.md b/docs/description/accessibility_trait_for_button.md new file mode 100644 index 0000000..f5139da --- /dev/null +++ b/docs/description/accessibility_trait_for_button.md @@ -0,0 +1,324 @@ +# Accessibility Trait for Button + +All views with tap gestures added should include the .isButton or the .isLink accessibility traits + +* **Identifier:** `accessibility_trait_for_button` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.1.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Rationale + +The accessibility button and link traits are used to tell assistive technologies that an element is tappable. When an element has one of these traits, VoiceOver will automatically read "button" or "link" after the element's label to let the user know that they can activate it. + +When using a UIKit `UIButton` or SwiftUI `Button` or `Link`, the button trait is added by default, but when you manually add a tap gesture recognizer to an element, you need to explicitly add the button or link trait. +In most cases the button trait should be used, but for buttons that open a URL in an external browser we use the link trait instead. This rule attempts to catch uses of the SwiftUI `.onTapGesture` modifier where the `.isButton` or `.isLink` trait is not explicitly applied. + +## Non Triggering Examples + +```swift +struct MyView: View { + var body: some View { + Button { + print("tapped") + } label: { + Text("Learn more") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Link("Open link", destination: myUrl) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .onTapGesture { + print("tapped - open URL") + } + .accessibility(addTraits: .isLink) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .accessibilityAddTraits(.isButton) + .onTapGesture { + print("tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .accessibility(addTraits: [.isButton, .isHeader]) + .onTapGesture { + print("tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .onTapGesture { + print("tapped - open URL") + } + .accessibilityAddTraits([.isHeader, .isLink]) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .onTapGesture(count: 1) { + print("tapped") + } + .accessibility(addTraits: .isButton) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .onTapGesture(count: 1, perform: { + print("tapped") + }) + .accessibility(addTraits: .isButton) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + // This rule does not include tap gestures with multiple taps for now. + // Custom gestures like this are also not very accessible, but require + // alternative ways to accomplish the same task with assistive tech. + .onTapGesture(count: 2) { + print("double-tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Label("Learn more", systemImage: "info.circle") + .onTapGesture(count: 1) { + print("tapped") + } + .accessibility(addTraits: .isButton) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + HStack { + Image(systemName: "info.circle") + Text("Learn more") + } + .onTapGesture { + print("tapped") + } + // This modifier is not strictly required — each subview will inherit the button trait. + // That said, grouping a tappable stack into a single element is a good way to reduce + // the number of swipes required for a VoiceOver user to navigate the page. + .accessibilityElement(children: .combine) + .accessibility(addTraits: .isButton) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .gesture(TapGesture().onEnded { + print("tapped") + }) + .accessibilityAddTraits(.isButton) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .simultaneousGesture(TapGesture(count: 1).onEnded { + print("tapped - open URL") + }) + .accessibilityAddTraits(.isLink) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .highPriorityGesture(TapGesture().onEnded { + print("tapped") + }) + .accessibility(addTraits: [.isButton]) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + Text("Learn more") + .gesture(TapGesture(count: 2).onEnded { + print("tapped") + }) + } +} +``` + +## Triggering Examples + +```swift +struct MyView: View { + var body: some View { + ↓Text("Learn more") + .onTapGesture { + print("tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Text("Learn more") + .accessibility(addTraits: .isHeader) + .onTapGesture { + print("tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Text("Learn more") + .onTapGesture(count: 1) { + print("tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Text("Learn more") + .onTapGesture(count: 1, perform: { + print("tapped") + }) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Label("Learn more", systemImage: "info.circle") + .onTapGesture(count: 1) { + print("tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓HStack { + Image(systemName: "info.circle") + Text("Learn more") + } + .onTapGesture { + print("tapped") + } + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Text("Learn more") + .gesture(TapGesture().onEnded { + print("tapped") + }) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Text("Learn more") + .simultaneousGesture(TapGesture(count: 1).onEnded { + print("tapped") + }) + } +} +``` + +```swift +struct MyView: View { + var body: some View { + ↓Text("Learn more") + .highPriorityGesture(TapGesture().onEnded { + print("tapped") + }) + } +} +``` \ No newline at end of file diff --git a/docs/description/anonymous_argument_in_multiline_closure.md b/docs/description/anonymous_argument_in_multiline_closure.md new file mode 100644 index 0000000..325bb1c --- /dev/null +++ b/docs/description/anonymous_argument_in_multiline_closure.md @@ -0,0 +1,74 @@ +# Anonymous Argument in Multiline Closure + +Use named arguments in multiline closures + +* **Identifier:** `anonymous_argument_in_multiline_closure` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Rationale + +In multiline closures, for clarity, prefer using named arguments + +```swift +closure { arg in + print(arg) +} +``` + +to anonymous arguments + +```swift +closure { + print(↓$0) +} +``` + +## Non Triggering Examples + +```swift +closure { $0 } +``` + +```swift +closure { print($0) } +``` + +```swift +closure { arg in + print(arg) +} +``` + +```swift +closure { arg in + nestedClosure { $0 + arg } +} +``` + +## Triggering Examples + +```swift +closure { + print(↓$0) +} +``` \ No newline at end of file diff --git a/docs/description/anyobject_protocol.md b/docs/description/anyobject_protocol.md new file mode 100644 index 0000000..032a3e8 --- /dev/null +++ b/docs/description/anyobject_protocol.md @@ -0,0 +1,58 @@ +# AnyObject Protocol + +Prefer using `AnyObject` over `class` for class-only protocols + +* **Identifier:** anyobject_protocol +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +protocol SomeProtocol {} +``` + +```swift +protocol SomeClassOnlyProtocol: AnyObject {} +``` + +```swift +protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {} +``` + +```swift +@objc protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {} +``` + +## Triggering Examples + +```swift +protocol SomeClassOnlyProtocol: ↓class {} +``` + +```swift +protocol SomeClassOnlyProtocol: ↓class, SomeInheritedProtocol {} +``` + +```swift +@objc protocol SomeClassOnlyProtocol: ↓class, SomeInheritedProtocol {} +``` \ No newline at end of file diff --git a/docs/description/array_init.md b/docs/description/array_init.md new file mode 100644 index 0000000..9cb5bb3 --- /dev/null +++ b/docs/description/array_init.md @@ -0,0 +1,144 @@ +# Array Init + +Prefer using `Array(seq)` over `seq.map { $0 }` to convert a sequence into an Array + +* **Identifier:** `array_init` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Rationale + +When converting the elements of a sequence directly into an `Array`, for clarity, prefer using the `Array` constructor over calling `map`. For example + +```swift +Array(foo) +``` + +rather than + +```swift +foo.↓map({ $0 }) +``` + +If some processing of the elements is required, then using `map` is fine. For example + +```swift +foo.map { !$0 } +``` + +Constructs like + +```swift +enum MyError: Error {} +let myResult: Result = .success("") +let result: Result = myResult.map { $0 } +``` + +may be picked up as false positives by the `array_init` rule. If your codebase contains constructs like this, consider using the `typesafe_array_init` analyzer rule instead. + +## Non Triggering Examples + +```swift +Array(foo) +``` + +```swift +foo.map { $0.0 } +``` + +```swift +foo.map { $1 } +``` + +```swift +foo.map { $0() } +``` + +```swift +foo.map { ((), $0) } +``` + +```swift +foo.map { $0! } +``` + +```swift +foo.map { $0! /* force unwrap */ } +``` + +```swift +foo.something { RouteMapper.map($0) } +``` + +```swift +foo.map { !$0 } +``` + +```swift +foo.map { /* a comment */ !$0 } +``` + +## Triggering Examples + +```swift +foo.↓map({ $0 }) +``` + +```swift +foo.↓map { $0 } +``` + +```swift +foo.↓map { return $0 } +``` + +```swift +foo.↓map { elem in + elem +} +``` + +```swift +foo.↓map { elem in + return elem +} +``` + +```swift +foo.↓map { (elem: String) in + elem +} +``` + +```swift +foo.↓map { elem -> String in + elem +} +``` + +```swift +foo.↓map { $0 /* a comment */ } +``` + +```swift +foo.↓map { /* a comment */ $0 } +``` \ No newline at end of file diff --git a/docs/description/async_without_await.md b/docs/description/async_without_await.md new file mode 100644 index 0000000..5ec020d --- /dev/null +++ b/docs/description/async_without_await.md @@ -0,0 +1,318 @@ +# Async Without Await + +Declaration should not be async if it doesn't use await + +* **Identifier:** `async_without_await` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func test() { + func test() async { + await test() + } +}, +``` + +```swift +func test() { + func test() async { + await test().value + } +}, +``` + +```swift +func test() async { + await scheduler.task { foo { bar() } } +} +``` + +```swift +func test() async { + perform(await try foo().value) +} +``` + +```swift +func test() async { + perform(try await foo()) +} +``` + +```swift +func test() async { + await perform() + func baz() { + qux() + } +} +``` + +```swift +let x: () async -> Void = { + await test() +} +``` + +```swift +let x: () async -> Void = { + await { await test() }() +} +``` + +```swift +func test() async { + await foo() +} +let x = { bar() } +``` + +```swift +let x: (() async -> Void)? = { + await { await test() }() +} +``` + +```swift +let x: (() async -> Void)? = nil +let x: () -> Void = { test() } +``` + +```swift +var test: Int { + get async throws { + try await foo() + } +} +var foo: Int { + get throws { + try bar() + } +} +``` + +```swift +init() async { + await foo() +} +``` + +```swift +init() async { + func test() async { + await foo() + } + await { await foo() }() +} +``` + +```swift +subscript(row: Int) -> Double { + get async { + await foo() + } +} +``` + +```swift +func foo() async -> Int +func bar() async -> Int +``` + +```swift +var foo: Int { get async } +var bar: Int { get async } +``` + +```swift +init(foo: bar) async +init(baz: qux) async +let baz = { qux() } +``` + +```swift +typealias Foo = () async -> Void +typealias Bar = () async -> Void +let baz = { qux() } +``` + +```swift +func test() async { + for await foo in bar {} +} +``` + +```swift +func test() async { + while let foo = await bar() {} +} +``` + +```swift +func test() async { + async let foo = bar() + let baz = await foo +} +``` + +```swift +func test() async { + async let foo = bar() + await foo +} +``` + +```swift +func test() async { + async let foo = bar() +} +``` + +```swift +func foo(bar: () async -> Void) { { } } +``` + +```swift +func foo(bar: () async -> Void = { await baz() }) { {} } +``` + +```swift +func foo() -> (() async -> Void)? { {} } +``` + +```swift +func foo( + bar: () async -> Void, + baz: () -> Void = {} +) { { } } +``` + +```swift +func foo(bar: () async -> Void = {}) { } +``` + +## Triggering Examples + +```swift +func test() ↓async { + perform() +} +``` + +```swift +func test() { + func baz() ↓async { + qux() + } + perform() + func baz() { + qux() + } +} +``` + +```swift +func test() ↓async { + func baz() async { + await qux() + } +} +``` + +```swift +func test() ↓async { + func foo() ↓async {} + let bar = { await foo() } +} +``` + +```swift +func test() ↓async { + let bar = { + func foo() ↓async {} + } +} +``` + +```swift +let x: (() ↓async -> Void)? = { test() } +``` + +```swift +var test: Int { + get ↓async throws { + foo() + } +} +``` + +```swift +var test: Int { + get ↓async throws { + func foo() ↓async {} + let bar = { await foo() } + } +} +``` + +```swift +var test: Int { + get throws { + func foo() {} + let bar: () ↓async -> Void = { foo() } + } +} +``` + +```swift +init() ↓async {} +``` + +```swift +init() ↓async { + func foo() ↓async {} + let bar: () ↓async -> Void = { foo() } +} +``` + +```swift +subscript(row: Int) -> Double { + get ↓async { + 1.0 + } +} +``` + +```swift +func test() ↓async { + for foo in bar {} +} +``` + +```swift +func test() ↓async { + while let foo = bar() {} +} +``` \ No newline at end of file diff --git a/docs/description/attribute_name_spacing.md b/docs/description/attribute_name_spacing.md new file mode 100644 index 0000000..885430b --- /dev/null +++ b/docs/description/attribute_name_spacing.md @@ -0,0 +1,130 @@ +# Attribute Name Spacing + +This rule prevents trailing spaces after attribute names, ensuring compatibility with Swift 6 where a space between an attribute name and the opening parenthesis results in a compilation error (e.g. `@MyPropertyWrapper ()`, `private (set)`). + +* **Identifier:** `attribute_name_spacing` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +private(set) var foo: Bool = false +``` + +```swift +fileprivate(set) var foo: Bool = false +``` + +```swift +@MainActor class Foo {} +``` + +```swift +func funcWithEscapingClosure(_ x: @escaping () -> Int) {} +``` + +```swift +@available(*, deprecated) +``` + +```swift +@MyPropertyWrapper(param: 2) +``` + +```swift +nonisolated(unsafe) var _value: X? +``` + +```swift +@testable import SwiftLintCore +``` + +```swift +func func_type_attribute_with_space(x: @convention(c) () -> Int) {} +``` + +```swift +@propertyWrapper +struct MyPropertyWrapper { + var wrappedValue: Int = 1 + + init(param: Int) {} +} +``` + +```swift +let closure2 = { @MainActor + (a: Int, b: Int) in +} +``` + +## Triggering Examples + +```swift +private ↓(set) var foo: Bool = false +``` + +```swift +fileprivate ↓(set) var foo: Bool = false +``` + +```swift +public ↓(set) var foo: Bool = false +``` + +```swift + public ↓(set) var foo: Bool = false +``` + +```swift +@ ↓MainActor class Foo {} +``` + +```swift +func funcWithEscapingClosure(_ x: @ ↓escaping () -> Int) {} +``` + +```swift +func funcWithEscapingClosure(_ x: @escaping↓() -> Int) {} +``` + +```swift +@available ↓(*, deprecated) +``` + +```swift +@MyPropertyWrapper ↓(param: 2) +``` + +```swift +nonisolated ↓(unsafe) var _value: X? +``` + +```swift +@MyProperty ↓() class Foo {} +``` + +```swift +let closure1 = { @MainActor ↓(a, b) in +} +``` \ No newline at end of file diff --git a/docs/description/attributes.md b/docs/description/attributes.md new file mode 100644 index 0000000..f8aa4a2 --- /dev/null +++ b/docs/description/attributes.md @@ -0,0 +1,443 @@ +# Attributes + +Attributes should be on their own lines in functions and types, but on the same line as variables and imports + +* **Identifier:** `attributes` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ attributes_with_arguments_always_on_line_above + + true +
+ always_on_same_line + + ["@IBAction", "@NSManaged"] +
+ always_on_line_above + + [] +
+ +## Rationale + +Erica Sadun says: + +> My take on things after the poll and after talking directly with a number of developers is this: Placing attributes like `@objc`, `@testable`, `@available`, `@discardableResult` on their own lines before a member declaration has become a conventional Swift style. + +> This approach limits declaration length. It allows a member to float below its attribute and supports flush-left access modifiers, so `internal`, `public`, etc appear in the leftmost column. Many developers mix-and-match styles for short Swift attributes like `@objc` + +See https://ericasadun.com/2016/10/02/quick-style-survey/ for discussion. + +SwiftLint's rule requires attributes to be on their own lines for functions and types, but on the same line for variables and imports. + +## Non Triggering Examples + +```swift +@objc var x: String +``` + +```swift +@objc private var x: String +``` + +```swift +@nonobjc var x: String +``` + +```swift +@IBOutlet private var label: UILabel +``` + +```swift +@IBOutlet @objc private var label: UILabel +``` + +```swift +@NSCopying var name: NSString +``` + +```swift +@NSManaged var name: String? +``` + +```swift +@IBInspectable var cornerRadius: CGFloat +``` + +```swift +@available(iOS 9.0, *) + let stackView: UIStackView +``` + +```swift +@NSManaged func addSomeObject(book: SomeObject) +``` + +```swift +@IBAction func buttonPressed(button: UIButton) +``` + +```swift +@objc + @IBAction func buttonPressed(button: UIButton) +``` + +```swift +@available(iOS 9.0, *) + func animate(view: UIStackView) +``` + +```swift +@available(*, deprecated, message: "A message") + func animate(view: UIStackView) +``` + +```swift +@nonobjc + final class X {} +``` + +```swift +@available(iOS 9.0, *) + class UIStackView {} +``` + +```swift +@NSApplicationMain + class AppDelegate: NSObject, NSApplicationDelegate {} +``` + +```swift +@UIApplicationMain + class AppDelegate: NSObject, UIApplicationDelegate {} +``` + +```swift +@IBDesignable + class MyCustomView: UIView {} +``` + +```swift +@testable import SourceKittenFramework +``` + +```swift +@objc(foo_x) + var x: String +``` + +```swift +@available(iOS 9.0, *) +@objc(abc_stackView) + let stackView: UIStackView +``` + +```swift +@objc(abc_addSomeObject:) + @NSManaged func addSomeObject(book: SomeObject) +``` + +```swift +@objc(ABCThing) + @available(iOS 9.0, *) + class Thing {} +``` + +```swift +class Foo: NSObject { + override var description: String { return "" } +} +``` + +```swift +class Foo: NSObject { + + override func setUp() {} +} +``` + +```swift +@objc +class ⽺ {} +``` + +```swift +extension Property { + + @available(*, unavailable, renamed: "isOptional") + public var optional: Bool { fatalError() } +} +``` + +```swift +@GKInspectable var maxSpeed: Float +``` + +```swift +@discardableResult + func a() -> Int +``` + +```swift +@objc + @discardableResult + func a() -> Int +``` + +```swift +func increase(f: @autoclosure () -> Int) -> Int +``` + +```swift +func foo(completionHandler: @escaping () -> Void) +``` + +```swift +private struct DefaultError: Error {} +``` + +```swift +@testable import foo + +private let bar = 1 +``` + +```swift +import XCTest +@testable import DeleteMe + +@available (iOS 11.0, *) +class DeleteMeTests: XCTestCase { +} +``` + +```swift +@objc +internal func foo(identifier: String, completion: @escaping (() -> Void)) {} +``` + +```swift +@objc +internal func foo(identifier: String, completion: @autoclosure (() -> Bool)) {} +``` + +```swift +func printBoolOrTrue(_ expression: @autoclosure () throws -> Bool?) rethrows { + try print(expression() ?? true) +} +``` + +```swift +import Foundation + +class MyClass: NSObject { + @objc( + first: + ) + static func foo(first: String) {} +} +``` + +```swift +func refreshable(action: @escaping @Sendable () async -> Void) -> some View { + modifier(RefreshableModifier(action: action)) +} +``` + +```swift +import AppKit + +@NSApplicationMain +@MainActor +final class AppDelegate: NSAppDelegate {} +``` + +## Triggering Examples + +```swift +@objc + ↓var x: String +``` + +```swift +@objc + + ↓var x: String +``` + +```swift +@objc + private ↓var x: String +``` + +```swift +@nonobjc + ↓var x: String +``` + +```swift +@IBOutlet + private ↓var label: UILabel +``` + +```swift +@IBOutlet + + private ↓var label: UILabel +``` + +```swift +@NSCopying + ↓var name: NSString +``` + +```swift +@NSManaged + ↓var name: String? +``` + +```swift +@IBInspectable + ↓var cornerRadius: CGFloat +``` + +```swift +@available(iOS 9.0, *) ↓let stackView: UIStackView +``` + +```swift +@NSManaged + ↓func addSomeObject(book: SomeObject) +``` + +```swift +@IBAction + ↓func buttonPressed(button: UIButton) +``` + +```swift +@IBAction + @objc + ↓func buttonPressed(button: UIButton) +``` + +```swift +@available(iOS 9.0, *) ↓func animate(view: UIStackView) +``` + +```swift +@nonobjc final ↓class X {} +``` + +```swift +@available(iOS 9.0, *) ↓class UIStackView {} +``` + +```swift +@available(iOS 9.0, *) + @objc ↓class UIStackView {} +``` + +```swift +@available(iOS 9.0, *) @objc + ↓class UIStackView {} +``` + +```swift +@available(iOS 9.0, *) + + ↓class UIStackView {} +``` + +```swift +@UIApplicationMain ↓class AppDelegate: NSObject, UIApplicationDelegate {} +``` + +```swift +@IBDesignable ↓class MyCustomView: UIView {} +``` + +```swift +@testable +↓import SourceKittenFramework +``` + +```swift +@testable + + +↓import SourceKittenFramework +``` + +```swift +@available(iOS 9.0, *) @objc(abc_stackView) + ↓let stackView: UIStackView +``` + +```swift +@objc(abc_addSomeObject:) @NSManaged + ↓func addSomeObject(book: SomeObject) +``` + +```swift +@objc(abc_addSomeObject:) + @NSManaged + ↓func addSomeObject(book: SomeObject) +``` + +```swift +@available(iOS 9.0, *) + @objc(ABCThing) ↓class Thing {} +``` + +```swift +@GKInspectable + ↓var maxSpeed: Float +``` + +```swift +@discardableResult ↓func a() -> Int +``` + +```swift +@objc + @discardableResult ↓func a() -> Int +``` + +```swift +@objc + + @discardableResult + ↓func a() -> Int +``` \ No newline at end of file diff --git a/docs/description/balanced_xctest_lifecycle.md b/docs/description/balanced_xctest_lifecycle.md new file mode 100644 index 0000000..cf64063 --- /dev/null +++ b/docs/description/balanced_xctest_lifecycle.md @@ -0,0 +1,150 @@ +# Balanced XCTest Life Cycle + +Test classes must implement balanced setUp and tearDown methods + +* **Identifier:** `balanced_xctest_lifecycle` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ test_parent_classes + + ["QuickSpec", "XCTestCase"] +
+ +## Rationale + +The `setUp` method of `XCTestCase` can be used to set up variables and resources before each test is run (or with the `class` variant, before all tests are run). + +This rule verifies that every class with an implementation of a `setUp` method also has a `tearDown` method (and vice versa). + +The `tearDown` method should be used to cleanup or reset any resources that could otherwise have any effects on subsequent tests, and to free up any instance variables. + +## Non Triggering Examples + +```swift +final class FooTests: XCTestCase { + override func setUp() {} + override func tearDown() {} +} +``` + +```swift +final class FooTests: XCTestCase { + override func setUpWithError() throws {} + override func tearDown() {} +} +``` + +```swift +final class FooTests: XCTestCase { + override func setUp() {} + override func tearDownWithError() throws {} +} +``` + +```swift +final class FooTests: XCTestCase { + override func setUpWithError() throws {} + override func tearDownWithError() throws {} +} +final class BarTests: XCTestCase { + override func setUpWithError() throws {} + override func tearDownWithError() throws {} +} +``` + +```swift +struct FooTests { + override func setUp() {} +} +class BarTests { + override func setUpWithError() throws {} +} +``` + +```swift +final class FooTests: XCTestCase { + override func setUpAlLExamples() {} +} +``` + +```swift +final class FooTests: XCTestCase { + class func setUp() {} + class func tearDown() {} +} +``` + +## Triggering Examples + +```swift +final class ↓FooTests: XCTestCase { + override func setUp() {} +} +``` + +```swift +final class ↓FooTests: XCTestCase { + override func setUpWithError() throws {} +} +``` + +```swift +final class FooTests: XCTestCase { + override func setUp() {} + override func tearDownWithError() throws {} +} +final class ↓BarTests: XCTestCase { + override func setUpWithError() throws {} +} +``` + +```swift +final class ↓FooTests: XCTestCase { + class func tearDown() {} +} +``` + +```swift +final class ↓FooTests: XCTestCase { + override func tearDown() {} +} +``` + +```swift +final class ↓FooTests: XCTestCase { + override func tearDownWithError() throws {} +} +``` + +```swift +final class FooTests: XCTestCase { + override func setUp() {} + override func tearDownWithError() throws {} +} +final class ↓BarTests: XCTestCase { + override func tearDownWithError() throws {} +} +``` \ No newline at end of file diff --git a/docs/description/blanket_disable_command.md b/docs/description/blanket_disable_command.md new file mode 100644 index 0000000..596d25b --- /dev/null +++ b/docs/description/blanket_disable_command.md @@ -0,0 +1,112 @@ +# Blanket Disable Command + +`swiftlint:disable` commands should use `next`, `this` or `previous` to disable rules for a single line, or `swiftlint:enable` to re-enable the rules immediately after the violations to be ignored, instead of disabling the rule for the rest of the file. + +* **Identifier:** `blanket_disable_command` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ allowed_rules + + ["file_header", "file_length", "file_name", "file_name_no_space", "single_test_class"] +
+ always_blanket_disable + + [] +
+ +## Rationale + +The intent of this rule is to prevent code like + +```swift +// swiftlint:disable force_unwrapping +let foo = bar! +``` + +which disables the `force_unwrapping` rule for the remainder of the file, instead of just for the specific violation. + +`next`, `this`, or `previous` can be used to restrict the disable command's scope to a single line, or it can be re-enabled after the violations. + +To disable this rule in code you will need to do something like + +```swift +// swiftlint:disable:next blanket_disable_command +// swiftlint:disable force_unwrapping +``` + +## Non Triggering Examples + +```swift +// swiftlint:disable unused_import +// swiftlint:enable unused_import +``` + +```swift +// swiftlint:disable unused_import unused_declaration +// swiftlint:enable unused_import +// swiftlint:enable unused_declaration +``` + +```swift +// swiftlint:disable:this unused_import +``` + +```swift +// swiftlint:disable:next unused_import +``` + +```swift +// swiftlint:disable:previous unused_import +``` + +## Triggering Examples + +```swift +// swiftlint:disable ↓unused_import +``` + +```swift +// swiftlint:disable unused_import ↓unused_declaration +// swiftlint:enable unused_import +``` + +```swift +// swiftlint:disable unused_import +// swiftlint:disable ↓unused_import +// swiftlint:enable unused_import +``` + +```swift +// swiftlint:enable ↓unused_import +``` + +```swift +// swiftlint:disable all +``` \ No newline at end of file diff --git a/docs/description/block_based_kvo.md b/docs/description/block_based_kvo.md new file mode 100644 index 0000000..156bb99 --- /dev/null +++ b/docs/description/block_based_kvo.md @@ -0,0 +1,52 @@ +# Block Based KVO + +Prefer the new block based KVO API with keypaths when using Swift 3.2 or later + +* **Identifier:** `block_based_kvo` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let observer = foo.observe(\.value, options: [.new]) { (foo, change) in + print(change.newValue) +} +``` + +## Triggering Examples + +```swift +class Foo: NSObject { + override ↓func observeValue(forKeyPath keyPath: String?, of object: Any?, + change: [NSKeyValueChangeKey : Any]?, + context: UnsafeMutableRawPointer?) {} +} +``` + +```swift +class Foo: NSObject { + override ↓func observeValue(forKeyPath keyPath: String?, of object: Any?, + change: Dictionary?, + context: UnsafeMutableRawPointer?) {} +} +``` \ No newline at end of file diff --git a/docs/description/capture_variable.md b/docs/description/capture_variable.md new file mode 100644 index 0000000..004bac6 --- /dev/null +++ b/docs/description/capture_variable.md @@ -0,0 +1,169 @@ +# Capture Variable + +Non-constant variables should not be listed in a closure's capture list to avoid confusion about closures capturing variables at creation time + +* **Identifier:** `capture_variable` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** Yes +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class C { + let i: Int + init(_ i: Int) { self.i = i } +} + +let j: Int = 0 +let c = C(1) + +let closure: () -> Void = { [j, c] in + print(c.i, j) +} + +closure() +``` + +```swift +let iGlobal: Int = 0 + +class C { + class var iClass: Int { 0 } + static let iStatic: Int = 0 + let iInstance: Int = 0 + + func callTest() { + var iLocal: Int = 0 + test { [unowned self, iGlobal, iInstance, iLocal, iClass=C.iClass, iStatic=C.iStatic] j in + print(iGlobal, iClass, iStatic, iInstance, iLocal, j) + } + } + + func test(_ completionHandler: @escaping (Int) -> Void) { + } +} +``` + +```swift +var j: Int! +j = 0 + +let closure: () -> Void = { [j] in + print(j) +} + +closure() +j = 1 +closure() +``` + +```swift +lazy var j: Int = { 0 }() + +let closure: () -> Void = { [j] in + print(j) +} + +closure() +j = 1 +closure() +``` + +## Triggering Examples + +```swift +var j: Int = 0 + +let closure: () -> Void = { [j] in + print(j) +} + +closure() +j = 1 +closure() +``` + +```swift +class C { + let i: Int + init(_ i: Int) { self.i = i } +} + +var c = C(0) +let closure: () -> Void = { [c] in + print(c.i) +} + +closure() +c = C(1) +closure() +``` + +```swift +var iGlobal: Int = 0 + +class C { + func callTest() { + test { [iGlobal] j in + print(iGlobal, j) + } + } + + func test(_ completionHandler: @escaping (Int) -> Void) { + } +} +``` + +```swift +class C { + static var iStatic: Int = 0 + + static func callTest() { + test { [↓iStatic] j in + print(iStatic, j) + } + } + + static func test(_ completionHandler: @escaping (Int) -> Void) { + completionHandler(2) + C.iStatic = 1 + completionHandler(3) + } +} + +C.callTest() +``` + +```swift +class C { + var iInstance: Int = 0 + + func callTest() { + test { [iInstance] j in + print(iInstance, j) + } + } + + func test(_ completionHandler: @escaping (Int) -> Void) { + } +} +``` \ No newline at end of file diff --git a/docs/description/class_delegate_protocol.md b/docs/description/class_delegate_protocol.md new file mode 100644 index 0000000..38f7ea8 --- /dev/null +++ b/docs/description/class_delegate_protocol.md @@ -0,0 +1,137 @@ +# Class Delegate Protocol + +Delegate protocols should be class-only so they can be weakly referenced + +* **Identifier:** `class_delegate_protocol` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Rationale + +Delegate protocols are usually `weak` to avoid retain cycles, or bad references to deallocated delegates. + +The `weak` operator is only supported for classes, and so this rule enforces that protocols ending in "Delegate" are class based. + +For example + +```swift +protocol FooDelegate: class {} +``` + +versus + +```swift +↓protocol FooDelegate {} +``` + +## Non Triggering Examples + +```swift +protocol FooDelegate: class {} +``` + +```swift +protocol FooDelegate: class, BarDelegate {} +``` + +```swift +protocol Foo {} +``` + +```swift +class FooDelegate {} +``` + +```swift +@objc protocol FooDelegate {} +``` + +```swift +@objc(MyFooDelegate) + protocol FooDelegate {} +``` + +```swift +protocol FooDelegate: BarDelegate {} +``` + +```swift +protocol FooDelegate: AnyObject {} +``` + +```swift +protocol FooDelegate: AnyObject & Foo {} +``` + +```swift +protocol FooDelegate: Foo, AnyObject & Foo {} +``` + +```swift +protocol FooDelegate: Foo & AnyObject & Bar {} +``` + +```swift +protocol FooDelegate: NSObjectProtocol {} +``` + +```swift +protocol FooDelegate where Self: BarDelegate {} +``` + +```swift +protocol FooDelegate where Self: BarDelegate & Bar {} +``` + +```swift +protocol FooDelegate where Self: Foo & BarDelegate & Bar {} +``` + +```swift +protocol FooDelegate where Self: AnyObject {} +``` + +```swift +protocol FooDelegate where Self: NSObjectProtocol {} +``` + +## Triggering Examples + +```swift +↓protocol FooDelegate {} +``` + +```swift +↓protocol FooDelegate: Bar {} +``` + +```swift +↓protocol FooDelegate: Foo & Bar {} +``` + +```swift +↓protocol FooDelegate where Self: StringProtocol {} +``` + +```swift +↓protocol FooDelegate where Self: A & B {} +``` \ No newline at end of file diff --git a/docs/description/closing_brace.md b/docs/description/closing_brace.md new file mode 100644 index 0000000..024d56e --- /dev/null +++ b/docs/description/closing_brace.md @@ -0,0 +1,48 @@ +# Closing Brace Spacing + +Closing brace with closing parenthesis should not have any whitespaces in the middle + +* **Identifier:** `closing_brace` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[].map({ }) +``` + +```swift +[].map( + { } +) +``` + +## Triggering Examples + +```swift +[].map({ ↓} ) +``` + +```swift +[].map({ ↓} ) +``` \ No newline at end of file diff --git a/docs/description/closure_body_length.md b/docs/description/closure_body_length.md new file mode 100644 index 0000000..2f25acd --- /dev/null +++ b/docs/description/closure_body_length.md @@ -0,0 +1,776 @@ +# Closure Body Length + +Closure bodies should not span too many lines + +* **Identifier:** `closure_body_length` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ warning + + 30 +
+ error + + 100 +
+ +## Rationale + +"Closure bodies should not span too many lines" says it all. + +Possibly you could refactor your closure code and extract some of it into a function. + +## Non Triggering Examples + +```swift +foo.bar { $0 } +``` + +```swift +foo.bar { toto in +} +``` + +```swift +foo.bar { toto in + let a0 = 0 + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + + + + + + + + + + + + + + + +} +``` + +```swift +foo.bar { toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 +} +``` + +```swift +foo.bar { toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + + + + + + + + + + + + + + + +} +``` + +```swift +foo.bar({ toto in +}) +``` + +```swift +foo.bar({ toto in + let a0 = 0 +}) +``` + +```swift +foo.bar({ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 +}) +``` + +```swift +foo.bar(label: { toto in +}) +``` + +```swift +foo.bar(label: { toto in + let a0 = 0 +}) +``` + +```swift +foo.bar(label: { toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 +}) +``` + +```swift +foo.bar(label: { toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 +}, anotherLabel: { toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 +}) +``` + +```swift +foo.bar(label: { toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 +}) { toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 +} +``` + +```swift +let foo: Bar = { toto in + let bar = Bar() + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + return bar +}() +``` + +## Triggering Examples + +```swift +foo.bar ↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 +} +``` + +```swift +foo.bar ↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + // toto + + + + + + + + + + +} +``` + +```swift +foo.bar(↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 +}) +``` + +```swift +foo.bar(label: ↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 +}) +``` + +```swift +foo.bar(label: ↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 +}, anotherLabel: ↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 +}) +``` + +```swift +foo.bar(label: ↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 +}) ↓{ toto in + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + let a29 = 0 + let a30 = 0 +} +``` + +```swift +let foo: Bar = ↓{ toto in + let bar = Bar() + let a0 = 0 + let a1 = 0 + let a2 = 0 + let a3 = 0 + let a4 = 0 + let a5 = 0 + let a6 = 0 + let a7 = 0 + let a8 = 0 + let a9 = 0 + let a10 = 0 + let a11 = 0 + let a12 = 0 + let a13 = 0 + let a14 = 0 + let a15 = 0 + let a16 = 0 + let a17 = 0 + let a18 = 0 + let a19 = 0 + let a20 = 0 + let a21 = 0 + let a22 = 0 + let a23 = 0 + let a24 = 0 + let a25 = 0 + let a26 = 0 + let a27 = 0 + let a28 = 0 + return bar +}() +``` \ No newline at end of file diff --git a/docs/description/closure_end_indentation.md b/docs/description/closure_end_indentation.md new file mode 100644 index 0000000..a10809c --- /dev/null +++ b/docs/description/closure_end_indentation.md @@ -0,0 +1,126 @@ +# Closure End Indentation + +Closure end should have the same indentation as the line that started it. + +* **Identifier:** `closure_end_indentation` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +SignalProducer(values: [1, 2, 3]) + .startWithNext { number in + print(number) + } + +``` + +```swift +[1, 2].map { $0 + 1 } + +``` + +```swift +return match(pattern: pattern, with: [.comment]).flatMap { range in + return Command(string: contents, range: range) +}.flatMap { command in + return command.expand() +} + +``` + +```swift +foo(foo: bar, + options: baz) { _ in } + +``` + +```swift +someReallyLongProperty.chainingWithAnotherProperty + .foo { _ in } +``` + +```swift +foo(abc, 123) +{ _ in } + +``` + +```swift +function( + closure: { x in + print(x) + }, + anotherClosure: { y in + print(y) + }) +``` + +```swift +function(parameter: param, + closure: { x in + print(x) +}) +``` + +```swift +function(parameter: param, closure: { x in + print(x) + }, + anotherClosure: { y in + print(y) + }) +``` + +```swift +(-variable).foo() +``` + +## Triggering Examples + +```swift +SignalProducer(values: [1, 2, 3]) + .startWithNext { number in + print(number) +↓} + +``` + +```swift +return match(pattern: pattern, with: [.comment]).flatMap { range in + return Command(string: contents, range: range) + ↓}.flatMap { command in + return command.expand() +↓} + +``` + +```swift +function( + closure: { x in + print(x) +↓}, + anotherClosure: { y in + print(y) +↓}) +``` \ No newline at end of file diff --git a/docs/description/closure_parameter_position.md b/docs/description/closure_parameter_position.md new file mode 100644 index 0000000..69eaeea --- /dev/null +++ b/docs/description/closure_parameter_position.md @@ -0,0 +1,156 @@ +# Closure Parameter Position + +Closure parameters should be on the same line as opening brace + +* **Identifier:** `closure_parameter_position` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[1, 2].map { $0 + 1 } +``` + +```swift +[1, 2].map({ $0 + 1 }) +``` + +```swift +[1, 2].map { number in + number + 1 +} +``` + +```swift +[1, 2].map { number -> Int in + number + 1 +} +``` + +```swift +[1, 2].map { (number: Int) -> Int in + number + 1 +} +``` + +```swift +[1, 2].map { [weak self] number in + number + 1 +} +``` + +```swift +[1, 2].something(closure: { number in + number + 1 +}) +``` + +```swift +let isEmpty = [1, 2].isEmpty() +``` + +```swift +rlmConfiguration.migrationBlock.map { rlmMigration in + return { migration, schemaVersion in + rlmMigration(migration.rlmMigration, schemaVersion) + } +} +``` + +```swift +let mediaView: UIView = { [weak self] index in + return UIView() +}(index) +``` + +## Triggering Examples + +```swift +[1, 2].map { + ↓number in + number + 1 +} +``` + +```swift +[1, 2].map { + ↓number -> Int in + number + 1 +} +``` + +```swift +[1, 2].map { + (↓number: Int) -> Int in + number + 1 +} +``` + +```swift +[1, 2].map { + [weak ↓self] ↓number in + number + 1 +} +``` + +```swift +[1, 2].map { [weak self] + ↓number in + number + 1 +} +``` + +```swift +[1, 2].map({ + ↓number in + number + 1 +}) +``` + +```swift +[1, 2].something(closure: { + ↓number in + number + 1 +}) +``` + +```swift +[1, 2].reduce(0) { + ↓sum, ↓number in + number + sum +}) +``` + +```swift +f.completionHandler = { + ↓thing in + doStuff() +} +``` + +```swift +foo { + [weak ↓self] in + self?.bar() +} +``` \ No newline at end of file diff --git a/docs/description/closure_spacing.md b/docs/description/closure_spacing.md new file mode 100644 index 0000000..bf8ea48 --- /dev/null +++ b/docs/description/closure_spacing.md @@ -0,0 +1,66 @@ +# Closure Spacing + +Closure expressions should have a single space inside each brace + +* **Identifier:** `closure_spacing` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[].map ({ $0.description }) +``` + +```swift +[].filter { $0.contains(location) } +``` + +```swift +extension UITableViewCell: ReusableView { } +``` + +```swift +extension UITableViewCell: ReusableView {} +``` + +## Triggering Examples + +```swift +[].filter↓{ $0.contains(location) } +``` + +```swift +[].filter(↓{$0.contains(location)}) +``` + +```swift +[].map(↓{$0}) +``` + +```swift +(↓{each in return result.contains(where: ↓{e in return e}) }).count +``` + +```swift +filter ↓{ sorted ↓{ $0 < $1}} +``` \ No newline at end of file diff --git a/docs/description/collection_alignment.md b/docs/description/collection_alignment.md new file mode 100644 index 0000000..4bc6f77 --- /dev/null +++ b/docs/description/collection_alignment.md @@ -0,0 +1,145 @@ +# Collection Element Alignment + +All elements in a collection literal should be vertically aligned + +* **Identifier:** `collection_alignment` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ align_colons + + false +
+ +## Non Triggering Examples + +```swift +doThings(arg: [ + "foo": 1, + "bar": 2, + "fizz": 2, + "buzz": 2 +]) +``` + +```swift +let abc = [ + "alpha": "a", + "beta": "b", + "gamma": "g", + "delta": "d", + "epsilon": "e" +] +``` + +```swift +let meals = [ + "breakfast": "oatmeal", + "lunch": "sandwich", + "dinner": "burger" +] +``` + +```swift +NSAttributedString(string: "…", attributes: [.font: UIFont.systemFont(ofSize: 12, weight: .regular), + .foregroundColor: UIColor(white: 0, alpha: 0.2)]) +``` + +```swift +let coordinates = [ + CLLocationCoordinate2D(latitude: 0, longitude: 33), + CLLocationCoordinate2D(latitude: 0, longitude: 66), + CLLocationCoordinate2D(latitude: 0, longitude: 99) +] +``` + +```swift +var evenNumbers: Set = [ + 2, + 4, + 6 +] +``` + +```swift +let abc = [1, 2, 3, 4] +``` + +```swift +let abc = [ + 1, 2, 3, 4 +] +``` + +```swift +let abc = [ + "foo": "bar", "fizz": "buzz" +] +``` + +## Triggering Examples + +```swift +doThings(arg: [ + "foo": 1, + "bar": 2, + ↓"fizz": 2, + ↓"buzz": 2 +]) +``` + +```swift +let abc = [ + "alpha": "a", + ↓"beta": "b", + "gamma": "g", + "delta": "d", + ↓"epsilon": "e" +] +``` + +```swift +let meals = [ + "breakfast": "oatmeal", + "lunch": "sandwich", + ↓"dinner": "burger" +] +``` + +```swift +let coordinates = [ + CLLocationCoordinate2D(latitude: 0, longitude: 33), + ↓CLLocationCoordinate2D(latitude: 0, longitude: 66), + CLLocationCoordinate2D(latitude: 0, longitude: 99) +] +``` + +```swift +var evenNumbers: Set = [ + 2, + ↓4, + 6 +] +``` \ No newline at end of file diff --git a/docs/description/colon.md b/docs/description/colon.md new file mode 100644 index 0000000..835f544 --- /dev/null +++ b/docs/description/colon.md @@ -0,0 +1,448 @@ +# Colon Spacing + +Colons should be next to the identifier when specifying a type and next to the key in dictionary literals + +* **Identifier:** `colon` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ flexible_right_spacing + + false +
+ apply_to_dictionaries + + true +
+ +## Non Triggering Examples + +```swift +let abc: Void +``` + +```swift +let abc: [Void: Void] +``` + +```swift +let abc: (Void, Void) +``` + +```swift +let abc: ([Void], String, Int) +``` + +```swift +let abc: [([Void], String, Int)] +``` + +```swift +let abc: String="def" +``` + +```swift +let abc: Int=0 +``` + +```swift +let abc: Enum=Enum.Value +``` + +```swift +func abc(def: Void) {} +``` + +```swift +func abc(def: Void, ghi: Void) {} +``` + +```swift +let abc: String = "abc:" +``` + +```swift +let abc = [Void: Void]() +``` + +```swift +let abc = [1: [3: 2], 3: 4] +``` + +```swift +let abc = ["string": "string"] +``` + +```swift +let abc = ["string:string": "string"] +``` + +```swift +let abc: [String: Int] +``` + +```swift +func foo(bar: [String: Int]) {} +``` + +```swift +func foo() -> [String: Int] { return [:] } +``` + +```swift +let abc: Any +``` + +```swift +let abc: [Any: Int] +``` + +```swift +let abc: [String: Any] +``` + +```swift +class Foo: Bar {} +``` + +```swift +class Foo: Bar {} +``` + +```swift +class Foo: Bar {} +``` + +```swift +class Foo: Bar {} +``` + +```swift +class Foo {} +``` + +```swift +object.method(x: /* comment */ 5) +``` + +```swift +switch foo { +case .bar: + _ = something() +} +``` + +```swift +object.method(x: 5, y: "string") +``` + +```swift +object.method(x: 5, y: + "string") +``` + +```swift +object.method(5, y: "string") +``` + +```swift +func abc() { def(ghi: jkl) } +``` + +```swift +func abc(def: Void) { ghi(jkl: mno) } +``` + +```swift +class ABC { let def = ghi(jkl: mno) } } +``` + +```swift +func foo() { let dict = [1: 1] } +``` + +```swift +let aaa = Self.bbb ? Self.ccc : Self.ddd else { +return nil +Example("} +``` + +```swift +range.flatMap(file.syntaxMap.kinds(inByteRange:)) ?? [] +``` + +```swift +@objc(receiveReply:) +public class func receiveReply(_ reply: bad_instruction_exception_reply_t) -> CInt { 0 } +``` + +```swift +switch str { +case "adlm", "adlam": return .adlam +case "aghb", "caucasianalbanian": return .caucasianAlbanian +default: return nil +} +``` + +```swift +precedencegroup PipelinePrecedence { + associativity: left +} +infix operator |> : PipelinePrecedence +``` + +```swift +switch scalar { + case 0x000A...0x000D /* LF ... CR */: return true + case 0x0085 /* NEXT LINE (NEL) */: return true + case 0x2028 /* LINE SEPARATOR */: return true + case 0x2029 /* PARAGRAPH SEPARATOR */: return true + default: return false +} +``` + +## Triggering Examples + +```swift +let abc↓:Void +``` + +```swift +let abc↓: Void +``` + +```swift +let abc↓ :Void +``` + +```swift +let abc↓ : Void +``` + +```swift +let abc↓ : [Void: Void] +``` + +```swift +let abc↓ : (Void, String, Int) +``` + +```swift +let abc↓ : ([Void], String, Int) +``` + +```swift +let abc↓ : [([Void], String, Int)] +``` + +```swift +let abc↓: (Void, String, Int) +``` + +```swift +let abc↓: ([Void], String, Int) +``` + +```swift +let abc↓: [([Void], String, Int)] +``` + +```swift +let abc↓ :String="def" +``` + +```swift +let abc↓ :Int=0 +``` + +```swift +let abc↓ :Int = 0 +``` + +```swift +let abc↓:Int=0 +``` + +```swift +let abc↓:Int = 0 +``` + +```swift +let abc↓:Enum=Enum.Value +``` + +```swift +func abc(def↓:Void) {} +``` + +```swift +func abc(def↓: Void) {} +``` + +```swift +func abc(def↓ :Void) {} +``` + +```swift +func abc(def↓ : Void) {} +``` + +```swift +func abc(def: Void, ghi↓ :Void) {} +``` + +```swift +let abc = [Void↓:Void]() +``` + +```swift +let abc = [Void↓ : Void]() +``` + +```swift +let abc = [Void↓: Void]() +``` + +```swift +let abc = [Void↓ : Void]() +``` + +```swift +let abc = [1: [3↓ : 2], 3: 4] +``` + +```swift +let abc = [1: [3↓ : 2], 3↓: 4] +``` + +```swift +let abc: [String↓ : Int] +``` + +```swift +let abc: [String↓:Int] +``` + +```swift +func foo(bar: [String↓ : Int]) {} +``` + +```swift +func foo(bar: [String↓:Int]) {} +``` + +```swift +func foo() -> [String↓ : Int] { return [:] } +``` + +```swift +func foo() -> [String↓:Int] { return [:] } +``` + +```swift +let abc↓ : Any +``` + +```swift +let abc: [Any↓ : Int] +``` + +```swift +let abc: [String↓ : Any] +``` + +```swift +class Foo↓ : Bar {} +``` + +```swift +class Foo↓:Bar {} +``` + +```swift +class Foo↓ : Bar {} +``` + +```swift +class Foo↓:Bar {} +``` + +```swift +class Foo↓:Bar {} +``` + +```swift +class Foo↓:Bar {} +``` + +```swift +class Foo {} +``` + +```swift +class Foo {} +``` + +```swift +object.method(x: 5, y↓ : "string") +``` + +```swift +object.method(x↓:5, y: "string") +``` + +```swift +object.method(x↓: 5, y: "string") +``` + +```swift +func abc() { def(ghi↓:jkl) } +``` + +```swift +func abc(def: Void) { ghi(jkl↓:mno) } +``` + +```swift +class ABC { let def = ghi(jkl↓:mno) } } +``` + +```swift +func foo() { let dict = [1↓ : 1] } +``` + +```swift +switch foo { +case .bar↓ : return baz +} +``` + +```swift +private var action↓:(() -> Void)? +``` \ No newline at end of file diff --git a/docs/description/comma.md b/docs/description/comma.md new file mode 100644 index 0000000..673ae80 --- /dev/null +++ b/docs/description/comma.md @@ -0,0 +1,110 @@ +# Comma Spacing + +There should be no space before and one after any comma + +* **Identifier:** `comma` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func abc(a: String, b: String) { } +``` + +```swift +abc(a: "string", b: "string" +``` + +```swift +enum a { case a, b, c } +``` + +```swift +func abc( + a: String, // comment + bcd: String // comment +) { +} +``` + +```swift +func abc( + a: String, + bcd: String +) { +} +``` + +```swift +#imageLiteral(resourceName: "foo,bar,baz") +``` + +```swift +kvcStringBuffer.advanced(by: rootKVCLength) + .storeBytes(of: 0x2E /* '.' */, as: CChar.self) +``` + +## Triggering Examples + +```swift +func abc(a: String↓ ,b: String) { } +``` + +```swift +func abc(a: String↓ ,b: String↓ ,c: String↓ ,d: String) { } +``` + +```swift +abc(a: "string"↓,b: "string" +``` + +```swift +enum a { case a↓ ,b } +``` + +```swift +let result = plus( + first: 3↓ , // #683 + second: 4 +) +``` + +```swift +Foo( + parameter: a.b.c, + tag: a.d, + value: a.identifier.flatMap { Int64($0) }↓ , + reason: Self.abcd() +) +``` + +```swift +return Foo(bar: .baz, title: fuzz, + message: My.Custom.message↓ , + another: parameter, doIt: true, + alignment: .center) +``` + +```swift +Logger.logError("Hat is too large"↓, info: []) +``` \ No newline at end of file diff --git a/docs/description/comma_inheritance.md b/docs/description/comma_inheritance.md new file mode 100644 index 0000000..836171c --- /dev/null +++ b/docs/description/comma_inheritance.md @@ -0,0 +1,94 @@ +# Comma Inheritance Rule + +Use commas to separate types in inheritance lists + +* **Identifier:** `comma_inheritance` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +struct A: Codable, Equatable {} +``` + +```swift +enum B: Codable, Equatable {} +``` + +```swift +class C: Codable, Equatable {} +``` + +```swift +protocol D: Codable, Equatable {} +``` + +```swift +typealias E = Equatable & Codable +``` + +```swift +func foo(_ param: T) {} +``` + +```swift +protocol G { + associatedtype Model: Codable, Equatable +} +``` + +## Triggering Examples + +```swift +struct A: Codable↓ & Equatable {} +``` + +```swift +struct A: Codable↓ & Equatable {} +``` + +```swift +struct A: Codable↓&Equatable {} +``` + +```swift +struct A: Codable↓& Equatable {} +``` + +```swift +enum B: Codable↓ & Equatable {} +``` + +```swift +class C: Codable↓ & Equatable {} +``` + +```swift +protocol D: Codable↓ & Equatable {} +``` + +```swift +protocol G { + associatedtype Model: Codable↓ & Equatable +} +``` \ No newline at end of file diff --git a/docs/description/comment_spacing.md b/docs/description/comment_spacing.md new file mode 100644 index 0000000..e3c6ed6 --- /dev/null +++ b/docs/description/comment_spacing.md @@ -0,0 +1,128 @@ +# Comment Spacing + +Prefer at least one space after slashes for comments + +* **Identifier:** `comment_spacing` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +// This is a comment +``` + +```swift +/// Triple slash comment +``` + +```swift +// Multiline double-slash +// comment +``` + +```swift +/// Multiline triple-slash +/// comment +``` + +```swift +/// Multiline triple-slash +/// - This is indented +``` + +```swift +// - MARK: Mark comment +``` + +```swift +//: Swift Playground prose section +``` + +```swift +/////////////////////////////////////////////// +// Comment with some lines of slashes boxing it +/////////////////////////////////////////////// +``` + +```swift +//:#localized(key: "SwiftPlaygroundLocalizedProse") +``` + +```swift +/* Asterisk comment */ +``` + +```swift +/* + Multiline asterisk comment +*/ +``` + +```swift +/*: + Multiline Swift Playground prose section +*/ +``` + +```swift +/*#-editable-code Swift Playground editable area*/default/*#-end-editable-code*/ +``` + +## Triggering Examples + +```swift +//↓Something +``` + +```swift +//↓MARK +``` + +```swift +//↓👨‍👨‍👦‍👦Something +``` + +```swift +func a() { + //↓This needs refactoring + print("Something") +} +//↓We should improve above function +``` + +```swift +///↓This is a comment +``` + +```swift +/// Multiline triple-slash +///↓This line is incorrect, though +``` + +```swift +//↓- MARK: Mark comment +``` + +```swift +//:↓Swift Playground prose section +``` \ No newline at end of file diff --git a/docs/description/compiler_protocol_init.md b/docs/description/compiler_protocol_init.md new file mode 100644 index 0000000..c4dfb5d --- /dev/null +++ b/docs/description/compiler_protocol_init.md @@ -0,0 +1,54 @@ +# Compiler Protocol Init + +The initializers declared in compiler protocols such as `ExpressibleByArrayLiteral` shouldn't be called directly. + +* **Identifier:** `compiler_protocol_init` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let set: Set = [1, 2] +``` + +```swift +let set = Set(array) +``` + +## Triggering Examples + +```swift +let set = ↓Set(arrayLiteral: 1, 2) +``` + +```swift +let set = ↓Set (arrayLiteral: 1, 2) +``` + +```swift +let set = ↓Set.init(arrayLiteral: 1, 2) +``` + +```swift +let set = ↓Set.init(arrayLiteral : 1, 2) +``` \ No newline at end of file diff --git a/docs/description/computed_accessors_order.md b/docs/description/computed_accessors_order.md new file mode 100644 index 0000000..b723aa8 --- /dev/null +++ b/docs/description/computed_accessors_order.md @@ -0,0 +1,291 @@ +# Computed Accessors Order + +Getter and setters in computed properties and subscripts should be in a consistent order. + +* **Identifier:** `computed_accessors_order` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ order + + get_set +
+ +## Non Triggering Examples + +```swift +class Foo { + var foo: Int { + get { return 3 } + set { _abc = newValue } + } +} +``` + +```swift +class Foo { + var foo: Int { + return 20 + } +} +``` + +```swift +class Foo { + static var foo: Int { + return 20 + } +} +``` + +```swift +class Foo { + static var foo: Int { + get { return 3 } + set { _abc = newValue } + } +} +``` + +```swift +class Foo { + var foo: Int +} +``` + +```swift +class Foo { + var foo: Int { + return getValueFromDisk() + } +} +``` + +```swift +class Foo { + var foo: String { + return "get" + } +} +``` + +```swift +protocol Foo { + var foo: Int { get } +``` + +```swift +protocol Foo { + var foo: Int { get set } +} +``` + +```swift +protocol Foo { + var foo: Int { set get } +``` + +```swift +class Foo { + var foo: Int { + struct Bar { + var bar: Int { + get { return 1 } + set { _ = newValue } + } + } + + return Bar().bar + } +} +``` + +```swift +var _objCTaggedPointerBits: UInt { + @inline(__always) get { return 0 } + set { print(newValue) } +} +``` + +```swift +var next: Int? { + mutating get { + defer { self.count += 1 } + return self.count + } + set { + self.count = newValue + } +} +``` + +```swift +extension Foo { + var bar: Bool { + get { _bar } + set { self._bar = newValue } + } +} +``` + +```swift +extension Foo { + var bar: Bool { + get { _bar } + set(newValue) { self._bar = newValue } + } +} +``` + +```swift +extension Reactive where Base: UITapGestureRecognizer { + var tapped: CocoaAction? { + get { + return associatedAction.withValue { $0.flatMap { $0.action } } + } + nonmutating set { + setAction(newValue) + } + } +} +``` + +```swift +extension Test { + var foo: Bool { + get { + bar?.boolValue ?? true // Comment mentioning word set which triggers violation + } + set { + bar = NSNumber(value: newValue as Bool) + } + } +} +``` + +```swift +class Foo { + subscript(i: Int) -> Int { + return 20 + } +} +``` + +```swift +class Foo { + subscript(i: Int) -> Int { + get { return 3 } + set { _abc = newValue } + } +} +``` + +```swift +protocol Foo { + subscript(i: Int) -> Int { get } +} +``` + +```swift +protocol Foo { + subscript(i: Int) -> Int { get set } +} +``` + +```swift +protocol Foo { + subscript(i: Int) -> Int { set get } +} +``` + +## Triggering Examples + +```swift +class Foo { + var foo: Int { + ↓set { + print(newValue) + } + get { + return 20 + } + } +} +``` + +```swift +class Foo { + static var foo: Int { + ↓set { + print(newValue) + } + get { + return 20 + } + } +} +``` + +```swift +var foo: Int { + ↓set { print(newValue) } + get { return 20 } +} +``` + +```swift +extension Foo { + var bar: Bool { + ↓set { print(bar) } + get { _bar } + } +} +``` + +```swift +class Foo { + var foo: Int { + ↓set { + print(newValue) + } + mutating get { + return 20 + } + } +} +``` + +```swift +class Foo { + subscript(i: Int) -> Int { + ↓set { + print(i) + } + get { + return 20 + } + } +} +``` \ No newline at end of file diff --git a/docs/description/conditional_returns_on_newline.md b/docs/description/conditional_returns_on_newline.md new file mode 100644 index 0000000..8edbd7c --- /dev/null +++ b/docs/description/conditional_returns_on_newline.md @@ -0,0 +1,101 @@ +# Conditional Returns on Newline + +Conditional statements should always return on the next line + +* **Identifier:** `conditional_returns_on_newline` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ if_only + + false +
+ +## Non Triggering Examples + +```swift +guard true else { + return true +} +``` + +```swift +guard true, + let x = true else { + return true +} +``` + +```swift +if true else { + return true +} +``` + +```swift +if true, + let x = true else { + return true +} +``` + +```swift +if textField.returnKeyType == .Next { +``` + +```swift +if true { // return } +``` + +```swift +guard something +else { return } +``` + +## Triggering Examples + +```swift +↓guard true else { return } +``` + +```swift +↓if true { return } +``` + +```swift +↓if true { break } else { return } +``` + +```swift +↓if true { break } else { return } +``` + +```swift +↓if true { return "YES" } else { return "NO" } +``` + +```swift +↓guard condition else { XCTFail(); return } +``` \ No newline at end of file diff --git a/docs/description/contains_over_filter_count.md b/docs/description/contains_over_filter_count.md new file mode 100644 index 0000000..9f5f799 --- /dev/null +++ b/docs/description/contains_over_filter_count.md @@ -0,0 +1,114 @@ +# Contains over Filter Count + +Prefer `contains` over comparing `filter(where:).count` to 0 + +* **Identifier:** `contains_over_filter_count` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count > 1 +``` + +```swift +let result = myList.filter { $0 % 2 == 0 }.count > 1 +``` + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count > 01 +``` + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count == 1 +``` + +```swift +let result = myList.filter { $0 % 2 == 0 }.count == 1 +``` + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count == 01 +``` + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count != 1 +``` + +```swift +let result = myList.filter { $0 % 2 == 0 }.count != 1 +``` + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count != 01 +``` + +```swift +let result = myList.contains(where: { $0 % 2 == 0 }) +``` + +```swift +let result = !myList.contains(where: { $0 % 2 == 0 }) +``` + +```swift +let result = myList.contains(10) +``` + +## Triggering Examples + +```swift +let result = ↓myList.filter(where: { $0 % 2 == 0 }).count > 0 +``` + +```swift +let result = ↓myList.filter { $0 % 2 == 0 }.count > 0 +``` + +```swift +let result = ↓myList.filter(where: someFunction).count > 0 +``` + +```swift +let result = ↓myList.filter(where: { $0 % 2 == 0 }).count == 0 +``` + +```swift +let result = ↓myList.filter { $0 % 2 == 0 }.count == 0 +``` + +```swift +let result = ↓myList.filter(where: someFunction).count == 0 +``` + +```swift +let result = ↓myList.filter(where: { $0 % 2 == 0 }).count != 0 +``` + +```swift +let result = ↓myList.filter { $0 % 2 == 0 }.count != 0 +``` + +```swift +let result = ↓myList.filter(where: someFunction).count != 0 +``` \ No newline at end of file diff --git a/docs/description/contains_over_filter_is_empty.md b/docs/description/contains_over_filter_is_empty.md new file mode 100644 index 0000000..87302db --- /dev/null +++ b/docs/description/contains_over_filter_is_empty.md @@ -0,0 +1,82 @@ +# Contains over Filter is Empty + +Prefer `contains` over using `filter(where:).isEmpty` + +* **Identifier:** `contains_over_filter_is_empty` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count > 1 +``` + +```swift +let result = myList.filter { $0 % 2 == 0 }.count > 1 +``` + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count == 1 +``` + +```swift +let result = myList.filter { $0 % 2 == 0 }.count == 1 +``` + +```swift +let result = myList.filter(where: { $0 % 2 == 0 }).count != 1 +``` + +```swift +let result = myList.filter { $0 % 2 == 0 }.count != 1 +``` + +```swift +let result = myList.contains(where: { $0 % 2 == 0 }) +``` + +```swift +let result = !myList.contains(where: { $0 % 2 == 0 }) +``` + +```swift +let result = myList.contains(10) +``` + +## Triggering Examples + +```swift +let result = ↓myList.filter(where: { $0 % 2 == 0 }).isEmpty +``` + +```swift +let result = !↓myList.filter(where: { $0 % 2 == 0 }).isEmpty +``` + +```swift +let result = ↓myList.filter { $0 % 2 == 0 }.isEmpty +``` + +```swift +let result = ↓myList.filter(where: someFunction).isEmpty +``` \ No newline at end of file diff --git a/docs/description/contains_over_first_not_nil.md b/docs/description/contains_over_first_not_nil.md new file mode 100644 index 0000000..def3739 --- /dev/null +++ b/docs/description/contains_over_first_not_nil.md @@ -0,0 +1,142 @@ +# Contains over First not Nil + +Prefer `contains` over `first(where:) != nil` and `firstIndex(where:) != nil`. + +* **Identifier:** `contains_over_first_not_nil` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let first = myList.first(where: { $0 % 2 == 0 }) +``` + +```swift +let first = myList.first { $0 % 2 == 0 } +``` + +```swift +let firstIndex = myList.firstIndex(where: { $0 % 2 == 0 }) +``` + +```swift +let firstIndex = myList.firstIndex { $0 % 2 == 0 } +``` + +## Triggering Examples + +```swift +↓myList.first { $0 % 2 == 0 } != nil +``` + +```swift +↓myList.first(where: { $0 % 2 == 0 }) != nil +``` + +```swift +↓myList.map { $0 + 1 }.first(where: { $0 % 2 == 0 }) != nil +``` + +```swift +↓myList.first(where: someFunction) != nil +``` + +```swift +↓myList.map { $0 + 1 }.first { $0 % 2 == 0 } != nil +``` + +```swift +(↓myList.first { $0 % 2 == 0 }) != nil +``` + +```swift +↓myList.first { $0 % 2 == 0 } == nil +``` + +```swift +↓myList.first(where: { $0 % 2 == 0 }) == nil +``` + +```swift +↓myList.map { $0 + 1 }.first(where: { $0 % 2 == 0 }) == nil +``` + +```swift +↓myList.first(where: someFunction) == nil +``` + +```swift +↓myList.map { $0 + 1 }.first { $0 % 2 == 0 } == nil +``` + +```swift +(↓myList.first { $0 % 2 == 0 }) == nil +``` + +```swift +↓myList.firstIndex { $0 % 2 == 0 } != nil +``` + +```swift +↓myList.firstIndex(where: { $0 % 2 == 0 }) != nil +``` + +```swift +↓myList.map { $0 + 1 }.firstIndex(where: { $0 % 2 == 0 }) != nil +``` + +```swift +↓myList.firstIndex(where: someFunction) != nil +``` + +```swift +↓myList.map { $0 + 1 }.firstIndex { $0 % 2 == 0 } != nil +``` + +```swift +(↓myList.firstIndex { $0 % 2 == 0 }) != nil +``` + +```swift +↓myList.firstIndex { $0 % 2 == 0 } == nil +``` + +```swift +↓myList.firstIndex(where: { $0 % 2 == 0 }) == nil +``` + +```swift +↓myList.map { $0 + 1 }.firstIndex(where: { $0 % 2 == 0 }) == nil +``` + +```swift +↓myList.firstIndex(where: someFunction) == nil +``` + +```swift +↓myList.map { $0 + 1 }.firstIndex { $0 % 2 == 0 } == nil +``` + +```swift +(↓myList.firstIndex { $0 % 2 == 0 }) == nil +``` \ No newline at end of file diff --git a/docs/description/contains_over_range_nil_comparison.md b/docs/description/contains_over_range_nil_comparison.md new file mode 100644 index 0000000..904106f --- /dev/null +++ b/docs/description/contains_over_range_nil_comparison.md @@ -0,0 +1,54 @@ +# Contains over Range Comparison to Nil + +Prefer `contains` over `range(of:) != nil` and `range(of:) == nil` + +* **Identifier:** `contains_over_range_nil_comparison` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let range = myString.range(of: "Test") +``` + +```swift +myString.contains("Test") +``` + +```swift +!myString.contains("Test") +``` + +```swift +resourceString.range(of: rule.regex, options: .regularExpression) != nil +``` + +## Triggering Examples + +```swift +↓myString.range(of: "Test") != nil +``` + +```swift +↓myString.range(of: "Test") == nil +``` \ No newline at end of file diff --git a/docs/description/contrasted_opening_brace.md b/docs/description/contrasted_opening_brace.md new file mode 100644 index 0000000..8a74549 --- /dev/null +++ b/docs/description/contrasted_opening_brace.md @@ -0,0 +1,279 @@ +# Contrasted Opening Brace + +The correct positioning of braces that introduce a block of code or member list is highly controversial. No matter which style is preferred, consistency is key. Apart from different tastes, the positioning of braces can also have a significant impact on the readability of the code, especially for visually impaired developers. This rule ensures that braces are on a separate line after the declaration to contrast the code block from the rest of the declaration. Comments between the declaration and the opening brace are respected. Check out the `opening_brace` rule for a different style. + +* **Identifier:** `contrasted_opening_brace` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func abc() +{ +} +``` + +```swift +[].map() +{ + $0 +} +``` + +```swift +[].map( + { + } +) +``` + +```swift +if let a = b +{ +} +``` + +```swift +while a == b +{ +} +``` + +```swift +guard let a = b else +{ +} +``` + +```swift +struct Rule +{ +} +``` + +```swift +struct Parent +{ + struct Child + { + let foo: Int + } +} +``` + +```swift +func f(rect: CGRect) +{ + { + let centre = CGPoint(x: rect.midX, y: rect.midY) + print(centre) + }() +} +``` + +```swift +func f(rect: CGRect) -> () -> Void +{ + { + let centre = CGPoint(x: rect.midX, y: rect.midY) + print(centre) + } +} +``` + +```swift +func f() -> () -> Void +{ + {} +} +``` + +```swift +@MyProperty class Rule: + NSObject +{ + var a: String + { + return "" + } +} +``` + +```swift +self.foo( + ( + "String parameter", + { "Do something here" } + ) +) +``` + +```swift +let pattern = #/(\{(?\w+)\})/# +``` + +```swift +if c +{} +else +{} +``` + +```swift + if c /* comment */ + { + return + } +``` + +```swift +if c1 +{ + return +} else if c2 +{ + return +} else if c3 +{ + return +} +``` + +```swift +let a = f.map +{ a in + a +} +``` + +## Triggering Examples + +```swift +func abc()↓{ +} +``` + +```swift +func abc() { } +``` + +```swift +func abc(a: A, + b: B) {} +``` + +```swift +[].map { $0 } +``` + +```swift +struct OldContentView: View ↓{ + @State private var showOptions = false + + var body: some View ↓{ + Button(action: { + self.showOptions.toggle() + })↓{ + Image(systemName: "gear") + } label: ↓{ + Image(systemName: "gear") + } + } +} +``` + +```swift +class Rule +{ + var a: String↓{ + return "" + } +} +``` + +```swift +@MyProperty class Rule +{ + var a: String + { + willSet↓{ + + } + didSet ↓{ + + } + } +} +``` + +```swift +precedencegroup Group ↓{ + assignment: true +} +``` + +```swift +if + "test".isEmpty ↓{ + // code here +} +``` + +```swift +if c ↓{} +else /* comment */ ↓{} +``` + +```swift +if c + ↓{ + // code here +} +``` + +```swift +if c1 ↓{ + return +} else if c2↓{ + return +} else if c3 + ↓{ + return +} +``` + +```swift +func f() +{ + return a.map + ↓{ $0 } +} +``` + +```swift +a ↓{ + $0 +} b: ↓{ + $1 +} +``` \ No newline at end of file diff --git a/docs/description/control_statement.md b/docs/description/control_statement.md new file mode 100644 index 0000000..2da5130 --- /dev/null +++ b/docs/description/control_statement.md @@ -0,0 +1,154 @@ +# Control Statement + +`if`, `for`, `guard`, `switch`, `while`, and `catch` statements shouldn't unnecessarily wrap their conditionals or arguments in parentheses + +* **Identifier:** `control_statement` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +if condition {} +``` + +```swift +if (a, b) == (0, 1) {} +``` + +```swift +if (a || b) && (c || d) {} +``` + +```swift +if (min...max).contains(value) {} +``` + +```swift +if renderGif(data) {} +``` + +```swift +renderGif(data) +``` + +```swift +guard condition else {} +``` + +```swift +while condition {} +``` + +```swift +do {} while condition {} +``` + +```swift +do { ; } while condition {} +``` + +```swift +switch foo {} +``` + +```swift +do {} catch let error as NSError {} +``` + +```swift +foo().catch(all: true) {} +``` + +```swift +if max(a, b) < c {} +``` + +```swift +switch (lhs, rhs) {} +``` + +```swift +if (f() { g() {} }) {} +``` + +```swift +if (a + f() {} == 1) {} +``` + +```swift +if ({ true }()) {} +``` + +## Triggering Examples + +```swift +↓if (condition) {} +``` + +```swift +↓if(condition) {} +``` + +```swift +↓if (condition == endIndex) {} +``` + +```swift +↓if ((a || b) && (c || d)) {} +``` + +```swift +↓if ((min...max).contains(value)) {} +``` + +```swift +↓guard (condition) else {} +``` + +```swift +↓while (condition) {} +``` + +```swift +↓while(condition) {} +``` + +```swift +do { ; } ↓while(condition) {} +``` + +```swift +do { ; } ↓while (condition) {} +``` + +```swift +↓switch (foo) {} +``` + +```swift +do {} ↓catch(let error as NSError) {} +``` + +```swift +↓if (max(a, b) < c) {} +``` \ No newline at end of file diff --git a/docs/description/convenience_type.md b/docs/description/convenience_type.md new file mode 100644 index 0000000..39043b0 --- /dev/null +++ b/docs/description/convenience_type.md @@ -0,0 +1,145 @@ +# Convenience Type + +Types used for hosting only static members should be implemented as a caseless enum to avoid instantiation + +* **Identifier:** `convenience_type` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +enum Math { // enum + public static let pi = 3.14 +} +``` + +```swift +// class with inheritance +class MathViewController: UIViewController { + public static let pi = 3.14 +} +``` + +```swift +@objc class Math: NSObject { // class visible to Obj-C + public static let pi = 3.14 +} +``` + +```swift +struct Math { // type with non-static declarations + public static let pi = 3.14 + public let randomNumber = 2 +} +``` + +```swift +class DummyClass {} +``` + +```swift +class Foo: NSObject { // class with Obj-C class property + class @objc let foo = 1 +} +``` + +```swift +class Foo: NSObject { // class with Obj-C static property + static @objc let foo = 1 +} +``` + +```swift +class Foo { // @objc class func can't exist on an enum + @objc class func foo() {} +} +``` + +```swift +class Foo { // @objc static func can't exist on an enum + @objc static func foo() {} +} +``` + +```swift +@objcMembers class Foo { // @objc static func can't exist on an enum + static func foo() {} +} +``` + +```swift +final class Foo { // final class, but @objc class func can't exist on an enum + @objc class func foo() {} +} +``` + +```swift +final class Foo { // final class, but @objc static func can't exist on an enum + @objc static func foo() {} +} +``` + +```swift +@globalActor actor MyActor { + static let shared = MyActor() +} +``` + +## Triggering Examples + +```swift +↓struct Math { + public static let pi = 3.14 +} +``` + +```swift +↓struct Math { + public static let pi = 3.14 + @available(*, unavailable) init() {} +} +``` + +```swift +final ↓class Foo { // final class can't be inherited + class let foo = 1 +} +``` + +```swift +↓class Foo { + class let foo = 1 +} +``` + +```swift +↓class Foo { + final class let foo = 1 +} +``` + +```swift +↓class SomeClass { + static func foo() {} +} +``` \ No newline at end of file diff --git a/docs/description/custom_rules.md b/docs/description/custom_rules.md new file mode 100644 index 0000000..8ce640c --- /dev/null +++ b/docs/description/custom_rules.md @@ -0,0 +1,10 @@ +# Custom Rules + +Create custom rules by providing a regex string. Optionally specify what syntax kinds to match against, the severity level, and what message to display. + +* **Identifier:** `custom_rules` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 \ No newline at end of file diff --git a/docs/description/cyclomatic_complexity.md b/docs/description/cyclomatic_complexity.md new file mode 100644 index 0000000..e93ec34 --- /dev/null +++ b/docs/description/cyclomatic_complexity.md @@ -0,0 +1,105 @@ +# Cyclomatic Complexity + +Complexity of function bodies should be limited. + +* **Identifier:** `cyclomatic_complexity` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 10 +
+ error + + 20 +
+ ignores_case_statements + + false +
+ +## Non Triggering Examples + +```swift +func f1() { + if true { + for _ in 1..5 { } + } + if false { } +} +``` + +```swift +func f(code: Int) -> Int { + switch code { + case 0: fallthrough + case 1: return 1 + case 2: return 1 + case 3: return 1 + case 4: return 1 + case 5: return 1 + case 6: return 1 + case 7: return 1 + case 8: return 1 + default: return 1 + } +} +``` + +```swift +func f1() { + if true {}; if true {}; if true {}; if true {}; if true {}; if true {} + func f2() { + if true {}; if true {}; if true {}; if true {}; if true {} + } +} +``` + +## Triggering Examples + +```swift +↓func f1() { + if true { + if true { + if false {} + } + } + if false {} + let i = 0 + switch i { + case 1: break + case 2: break + case 3: break + case 4: break + default: break + } + for _ in 1...5 { + guard true else { + return + } + } +} +``` \ No newline at end of file diff --git a/docs/description/deployment_target.md b/docs/description/deployment_target.md new file mode 100644 index 0000000..47c7d94 --- /dev/null +++ b/docs/description/deployment_target.md @@ -0,0 +1,232 @@ +# Deployment Target + +Availability checks or attributes shouldn't be using older versions that are satisfied by the deployment target. + +* **Identifier:** `deployment_target` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ iOSApplicationExtension_deployment_target + + 7.0 +
+ iOS_deployment_target + + 7.0 +
+ macOSApplicationExtension_deployment_target + + 10.9 +
+ macOS_deployment_target + + 10.9 +
+ tvOSApplicationExtension_deployment_target + + 9.0 +
+ tvOS_deployment_target + + 9.0 +
+ watchOSApplicationExtension_deployment_target + + 1.0 +
+ watchOS_deployment_target + + 1.0 +
+ +## Non Triggering Examples + +```swift +@available(iOS 12.0, *) +class A {} +``` + +```swift +@available(iOSApplicationExtension 13.0, *) +class A {} +``` + +```swift +@available(watchOS 4.0, *) +class A {} +``` + +```swift +@available(watchOSApplicationExtension 4.0, *) +class A {} +``` + +```swift +@available(swift 3.0.2) +class A {} +``` + +```swift +class A {} +``` + +```swift +if #available(iOS 10.0, *) {} +``` + +```swift +if #available(iOS 10, *) {} +``` + +```swift +guard #available(iOS 12.0, *) else { return } +``` + +```swift +#if #unavailable(iOS 15.0) {} +``` + +```swift +#guard #unavailable(iOS 15.0) {} else { return } +``` + +## Triggering Examples + +```swift +↓@available(iOS 6.0, *) +class A {} +``` + +```swift +↓@available(iOSApplicationExtension 6.0, *) +class A {} +``` + +```swift +↓@available(iOS 7.0, *) +class A {} +``` + +```swift +↓@available(iOS 6, *) +class A {} +``` + +```swift +↓@available(iOS 6.0, macOS 10.12, *) + class A {} +``` + +```swift +↓@available(macOS 10.12, iOS 6.0, *) + class A {} +``` + +```swift +↓@available(macOS 10.7, *) +class A {} +``` + +```swift +↓@available(macOSApplicationExtension 10.7, *) +class A {} +``` + +```swift +↓@available(OSX 10.7, *) +class A {} +``` + +```swift +↓@available(watchOS 0.9, *) +class A {} +``` + +```swift +↓@available(watchOSApplicationExtension 0.9, *) +class A {} +``` + +```swift +↓@available(tvOS 8, *) +class A {} +``` + +```swift +↓@available(tvOSApplicationExtension 8, *) +class A {} +``` + +```swift +if ↓#available(iOS 6.0, *) {} +``` + +```swift +if ↓#available(iOS 6, *) {} +``` + +```swift +guard ↓#available(iOS 6.0, *) else { return } +``` + +```swift +if ↓#unavailable(iOS 7.0) {} +``` + +```swift +if ↓#unavailable(iOS 6.9) {} +``` + +```swift +guard ↓#unavailable(iOS 7.0) {} else { return } +``` \ No newline at end of file diff --git a/docs/description/description.json b/docs/description/description.json new file mode 100644 index 0000000..154b460 --- /dev/null +++ b/docs/description/description.json @@ -0,0 +1,1221 @@ +[ { + "patternId" : "accessibility_label_for_image", + "title" : "Accessibility Label for Image", + "description" : "Images that provide context should have an accessibility label or should be explicitly hidden from accessibility", + "parameters" : [ ] +}, { + "patternId" : "accessibility_trait_for_button", + "title" : "Accessibility Trait for Button", + "description" : "All views with tap gestures added should include the .isButton or the .isLink accessibility traits", + "parameters" : [ ] +}, { + "patternId" : "anonymous_argument_in_multiline_closure", + "title" : "Anonymous Argument in Multiline Closure", + "description" : "Use named arguments in multiline closures", + "parameters" : [ ] +}, { + "patternId" : "array_init", + "title" : "Array Init", + "description" : "Prefer using `Array(seq)` over `seq.map { $0 }` to convert a sequence into an Array", + "parameters" : [ ] +}, { + "patternId" : "async_without_await", + "title" : "Async Without Await", + "description" : "Declaration should not be async if it doesn't use await", + "parameters" : [ ] +}, { + "patternId" : "attribute_name_spacing", + "title" : "Attribute Name Spacing", + "description" : "This rule prevents trailing spaces after attribute names, ensuring compatibility with Swift 6 where a space between an attribute name and the opening parenthesis results in a compilation error (e.g. `@MyPropertyWrapper ()`, `private (set)`).", + "parameters" : [ ] +}, { + "patternId" : "attributes", + "title" : "Attributes", + "description" : "Attributes should be on their own lines in functions and types, but on the same line as variables and imports", + "parameters" : [ ] +}, { + "patternId" : "balanced_xctest_lifecycle", + "title" : "Balanced XCTest Life Cycle", + "description" : "Test classes must implement balanced setUp and tearDown methods", + "parameters" : [ ] +}, { + "patternId" : "blanket_disable_command", + "title" : "Blanket Disable Command", + "description" : "`swiftlint:disable` commands should use `next`, `this` or `previous` to disable rules for a single line, or `swiftlint:enable` to re-enable the rules immediately after the violations to be ignored, instead of disabling the rule for the rest of the file.", + "parameters" : [ ] +}, { + "patternId" : "block_based_kvo", + "title" : "Block Based KVO", + "description" : "Prefer the new block based KVO API with keypaths when using Swift 3.2 or later", + "parameters" : [ ] +}, { + "patternId" : "capture_variable", + "title" : "Capture Variable", + "description" : "Non-constant variables should not be listed in a closure's capture list to avoid confusion about closures capturing variables at creation time", + "parameters" : [ ] +}, { + "patternId" : "class_delegate_protocol", + "title" : "Class Delegate Protocol", + "description" : "Delegate protocols should be class-only so they can be weakly referenced", + "parameters" : [ ] +}, { + "patternId" : "closing_brace", + "title" : "Closing Brace Spacing", + "description" : "Closing brace with closing parenthesis should not have any whitespaces in the middle", + "parameters" : [ ] +}, { + "patternId" : "closure_body_length", + "title" : "Closure Body Length", + "description" : "Closure bodies should not span too many lines", + "parameters" : [ ] +}, { + "patternId" : "closure_end_indentation", + "title" : "Closure End Indentation", + "description" : "Closure end should have the same indentation as the line that started it.", + "parameters" : [ ] +}, { + "patternId" : "closure_parameter_position", + "title" : "Closure Parameter Position", + "description" : "Closure parameters should be on the same line as opening brace", + "parameters" : [ ] +}, { + "patternId" : "closure_spacing", + "title" : "Closure Spacing", + "description" : "Closure expressions should have a single space inside each brace", + "parameters" : [ ] +}, { + "patternId" : "collection_alignment", + "title" : "Collection Element Alignment", + "description" : "All elements in a collection literal should be vertically aligned", + "parameters" : [ ] +}, { + "patternId" : "colon", + "title" : "Colon Spacing", + "description" : "Colons should be next to the identifier when specifying a type and next to the key in dictionary literals", + "parameters" : [ ] +}, { + "patternId" : "comma", + "title" : "Comma Spacing", + "description" : "There should be no space before and one after any comma", + "parameters" : [ ] +}, { + "patternId" : "comma_inheritance", + "title" : "Comma Inheritance Rule", + "description" : "Use commas to separate types in inheritance lists", + "parameters" : [ ] +}, { + "patternId" : "comment_spacing", + "title" : "Comment Spacing", + "description" : "Prefer at least one space after slashes for comments", + "parameters" : [ ] +}, { + "patternId" : "compiler_protocol_init", + "title" : "Compiler Protocol Init", + "description" : "The initializers declared in compiler protocols such as `ExpressibleByArrayLiteral` shouldn't be called directly.", + "parameters" : [ ] +}, { + "patternId" : "computed_accessors_order", + "title" : "Computed Accessors Order", + "description" : "Getter and setters in computed properties and subscripts should be in a consistent order.", + "parameters" : [ ] +}, { + "patternId" : "conditional_returns_on_newline", + "title" : "Conditional Returns on Newline", + "description" : "Conditional statements should always return on the next line", + "parameters" : [ ] +}, { + "patternId" : "contains_over_filter_count", + "title" : "Contains over Filter Count", + "description" : "Prefer `contains` over comparing `filter(where:).count` to 0", + "parameters" : [ ] +}, { + "patternId" : "contains_over_filter_is_empty", + "title" : "Contains over Filter is Empty", + "description" : "Prefer `contains` over using `filter(where:).isEmpty`", + "parameters" : [ ] +}, { + "patternId" : "contains_over_first_not_nil", + "title" : "Contains over First not Nil", + "description" : "Prefer `contains` over `first(where:) != nil` and `firstIndex(where:) != nil`.", + "parameters" : [ ] +}, { + "patternId" : "contains_over_range_nil_comparison", + "title" : "Contains over Range Comparison to Nil", + "description" : "Prefer `contains` over `range(of:) != nil` and `range(of:) == nil`", + "parameters" : [ ] +}, { + "patternId" : "contrasted_opening_brace", + "title" : "Contrasted Opening Brace", + "description" : "The correct positioning of braces that introduce a block of code or member list is highly controversial. No matter which style is preferred, consistency is key. Apart from different tastes, the positioning of braces can also have a significant impact on the readability of the code, especially for visually impaired developers. This rule ensures that braces are on a separate line after the declaration to contrast the code block from the rest of the declaration.", + "parameters" : [ ] +}, { + "patternId" : "control_statement", + "title" : "Control Statement", + "description" : "`if`, `for`, `guard`, `switch`, `while`, and `catch` statements shouldn't unnecessarily wrap their conditionals or arguments in parentheses", + "parameters" : [ ] +}, { + "patternId" : "convenience_type", + "title" : "Convenience Type", + "description" : "Types used for hosting only static members should be implemented as a caseless enum to avoid instantiation", + "parameters" : [ ] +}, { + "patternId" : "custom_rules", + "title" : "Custom Rules", + "description" : "Create custom rules by providing a regex string. Optionally specify what syntax kinds to match against, the severity level, and what message to display.", + "parameters" : [ ] +}, { + "patternId" : "cyclomatic_complexity", + "title" : "Cyclomatic Complexity", + "description" : "Complexity of function bodies should be limited.", + "parameters" : [ ] +}, { + "patternId" : "deployment_target", + "title" : "Deployment Target", + "description" : "Availability checks or attributes shouldn't be using older versions that are satisfied by the deployment target.", + "parameters" : [ ] +}, { + "patternId" : "direct_return", + "title" : "Direct Return", + "description" : "Directly return the expression instead of assigning it to a variable first", + "parameters" : [ ] +}, { + "patternId" : "discarded_notification_center_observer", + "title" : "Discarded Notification Center Observer", + "description" : "When registering for a notification using a block, the opaque observer that is returned should be stored so it can be removed later", + "parameters" : [ ] +}, { + "patternId" : "discouraged_assert", + "title" : "Discouraged Assert", + "description" : "Prefer `assertionFailure()` and/or `preconditionFailure()` over `assert(false)`", + "parameters" : [ ] +}, { + "patternId" : "discouraged_direct_init", + "title" : "Discouraged Direct Initialization", + "description" : "Discouraged direct initialization of types that can be harmful", + "parameters" : [ ] +}, { + "patternId" : "discouraged_none_name", + "title" : "Discouraged None Name", + "description" : "Enum cases and static members named `none` are discouraged as they can conflict with `Optional.none`.", + "parameters" : [ ] +}, { + "patternId" : "discouraged_object_literal", + "title" : "Discouraged Object Literal", + "description" : "Prefer initializers over object literals", + "parameters" : [ ] +}, { + "patternId" : "discouraged_optional_boolean", + "title" : "Discouraged Optional Boolean", + "description" : "Prefer non-optional booleans over optional booleans", + "parameters" : [ ] +}, { + "patternId" : "discouraged_optional_collection", + "title" : "Discouraged Optional Collection", + "description" : "Prefer empty collection over optional collection", + "parameters" : [ ] +}, { + "patternId" : "duplicate_conditions", + "title" : "Duplicate Conditions", + "description" : "Duplicate sets of conditions in the same branch instruction should be avoided", + "parameters" : [ ] +}, { + "patternId" : "duplicate_enum_cases", + "title" : "Duplicate Enum Cases", + "description" : "Enum shouldn't contain multiple cases with the same name", + "parameters" : [ ] +}, { + "patternId" : "duplicate_imports", + "title" : "Duplicate Imports", + "description" : "Imports should be unique", + "parameters" : [ ] +}, { + "patternId" : "duplicated_key_in_dictionary_literal", + "title" : "Duplicated Key in Dictionary Literal", + "description" : "Dictionary literals with duplicated keys will crash at runtime", + "parameters" : [ ] +}, { + "patternId" : "dynamic_inline", + "title" : "Dynamic Inline", + "description" : "Avoid using 'dynamic' and '@inline(__always)' together", + "parameters" : [ ] +}, { + "patternId" : "empty_collection_literal", + "title" : "Empty Collection Literal", + "description" : "Prefer checking `isEmpty` over comparing collection to an empty array or dictionary literal", + "parameters" : [ ] +}, { + "patternId" : "empty_count", + "title" : "Empty Count", + "description" : "Prefer checking `isEmpty` over comparing `count` to zero", + "parameters" : [ ] +}, { + "patternId" : "empty_enum_arguments", + "title" : "Empty Enum Arguments", + "description" : "Arguments can be omitted when matching enums with associated values if they are not used", + "parameters" : [ ] +}, { + "patternId" : "empty_parameters", + "title" : "Empty Parameters", + "description" : "Prefer `() -> ` over `Void -> `", + "parameters" : [ ] +}, { + "patternId" : "empty_parentheses_with_trailing_closure", + "title" : "Empty Parentheses with Trailing Closure", + "description" : "When using trailing closures, empty parentheses should be avoided after the method call", + "parameters" : [ ] +}, { + "patternId" : "empty_string", + "title" : "Empty String", + "description" : "Prefer checking `isEmpty` over comparing `string` to an empty string literal", + "parameters" : [ ] +}, { + "patternId" : "empty_xctest_method", + "title" : "Empty XCTest Method", + "description" : "Empty XCTest method should be avoided", + "parameters" : [ ] +}, { + "patternId" : "enum_case_associated_values_count", + "title" : "Enum Case Associated Values Count", + "description" : "The number of associated values in an enum case should be low.", + "parameters" : [ ] +}, { + "patternId" : "expiring_todo", + "title" : "Expiring Todo", + "description" : "TODOs and FIXMEs should be resolved prior to their expiry date.", + "parameters" : [ ] +}, { + "patternId" : "explicit_acl", + "title" : "Explicit ACL", + "description" : "All declarations should specify Access Control Level keywords explicitly", + "parameters" : [ ] +}, { + "patternId" : "explicit_enum_raw_value", + "title" : "Explicit Enum Raw Value", + "description" : "Enums should be explicitly assigned their raw values", + "parameters" : [ ] +}, { + "patternId" : "explicit_init", + "title" : "Explicit Init", + "description" : "Explicitly calling .init() should be avoided", + "parameters" : [ ] +}, { + "patternId" : "explicit_self", + "title" : "Explicit Self", + "description" : "Instance variables and functions should be explicitly accessed with 'self.'", + "parameters" : [ ] +}, { + "patternId" : "explicit_top_level_acl", + "title" : "Explicit Top Level ACL", + "description" : "Top-level declarations should specify Access Control Level keywords explicitly", + "parameters" : [ ] +}, { + "patternId" : "explicit_type_interface", + "title" : "Explicit Type Interface", + "description" : "Properties should have a type interface", + "parameters" : [ ] +}, { + "patternId" : "extension_access_modifier", + "title" : "Extension Access Modifier", + "description" : "Prefer to use extension access modifiers", + "parameters" : [ ] +}, { + "patternId" : "fallthrough", + "title" : "Fallthrough", + "description" : "Fallthrough should be avoided", + "parameters" : [ ] +}, { + "patternId" : "fatal_error_message", + "title" : "Fatal Error Message", + "description" : "A fatalError call should have a message", + "parameters" : [ ] +}, { + "patternId" : "file_header", + "title" : "File Header", + "description" : "Header comments should be consistent with project patterns. The SWIFTLINT_CURRENT_FILENAME placeholder can optionally be used in the required and forbidden patterns. It will be replaced by the real file name.", + "parameters" : [ ] +}, { + "patternId" : "file_length", + "title" : "File Length", + "description" : "Files should not span too many lines.", + "parameters" : [ ] +}, { + "patternId" : "file_name", + "title" : "File Name", + "description" : "File name should match a type or extension declared in the file (if any)", + "parameters" : [ ] +}, { + "patternId" : "file_name_no_space", + "title" : "File Name no Space", + "description" : "File name should not contain any whitespace", + "parameters" : [ ] +}, { + "patternId" : "file_types_order", + "title" : "File Types Order", + "description" : "Specifies how the types within a file should be ordered.", + "parameters" : [ ] +}, { + "patternId" : "final_test_case", + "title" : "Final Test Case", + "description" : "Test cases should be final", + "parameters" : [ ] +}, { + "patternId" : "first_where", + "title" : "First Where", + "description" : "Prefer using `.first(where:)` over `.filter { }.first` in collections", + "parameters" : [ ] +}, { + "patternId" : "flatmap_over_map_reduce", + "title" : "Flat Map over Map Reduce", + "description" : "Prefer `flatMap` over `map` followed by `reduce([], +)`", + "parameters" : [ ] +}, { + "patternId" : "for_where", + "title" : "Prefer For-Where", + "description" : "`where` clauses are preferred over a single `if` inside a `for`", + "parameters" : [ ] +}, { + "patternId" : "force_cast", + "title" : "Force Cast", + "description" : "Force casts should be avoided", + "parameters" : [ ] +}, { + "patternId" : "force_try", + "title" : "Force Try", + "description" : "Force tries should be avoided", + "parameters" : [ ] +}, { + "patternId" : "force_unwrapping", + "title" : "Force Unwrapping", + "description" : "Force unwrapping should be avoided", + "parameters" : [ ] +}, { + "patternId" : "function_body_length", + "title" : "Function Body Length", + "description" : "Function bodies should not span too many lines", + "parameters" : [ ] +}, { + "patternId" : "function_default_parameter_at_end", + "title" : "Function Default Parameter at End", + "description" : "Prefer to locate parameters with defaults toward the end of the parameter list", + "parameters" : [ ] +}, { + "patternId" : "function_parameter_count", + "title" : "Function Parameter Count", + "description" : "Number of function parameters should be low.", + "parameters" : [ ] +}, { + "patternId" : "generic_type_name", + "title" : "Generic Type Name", + "description" : "Generic type name should only contain alphanumeric characters, start with an uppercase character and span between 1 and 20 characters in length.", + "parameters" : [ ] +}, { + "patternId" : "ibinspectable_in_extension", + "title" : "IBInspectable in Extension", + "description" : "Extensions shouldn't add @IBInspectable properties", + "parameters" : [ ] +}, { + "patternId" : "identical_operands", + "title" : "Identical Operands", + "description" : "Comparing two identical operands is likely a mistake", + "parameters" : [ ] +}, { + "patternId" : "identifier_name", + "title" : "Identifier Name", + "description" : "Identifier names should only contain alphanumeric characters and start with a lowercase character or should only contain capital letters. In an exception to the above, variable names may start with a capital letter when they are declared as static. Variable names should not be too long or too short.", + "parameters" : [ ] +}, { + "patternId" : "implicit_getter", + "title" : "Implicit Getter", + "description" : "Computed read-only properties and subscripts should avoid using the get keyword.", + "parameters" : [ ] +}, { + "patternId" : "implicit_return", + "title" : "Implicit Return", + "description" : "Prefer implicit returns in closures, functions and getters", + "parameters" : [ ] +}, { + "patternId" : "implicitly_unwrapped_optional", + "title" : "Implicitly Unwrapped Optional", + "description" : "Implicitly unwrapped optionals should be avoided when possible", + "parameters" : [ ] +}, { + "patternId" : "inclusive_language", + "title" : "Inclusive Language", + "description" : "Identifiers should use inclusive language that avoids discrimination against groups of people based on race, gender, or socioeconomic status.", + "parameters" : [ ] +}, { + "patternId" : "indentation_width", + "title" : "Indentation Width", + "description" : "Indent code using either one tab or the configured amount of spaces, unindent to match previous indentations. Don't indent the first line.", + "parameters" : [ ] +}, { + "patternId" : "invalid_swiftlint_command", + "title" : "Invalid SwiftLint Command", + "description" : "swiftlint command is invalid", + "parameters" : [ ] +}, { + "patternId" : "is_disjoint", + "title" : "Is Disjoint", + "description" : "Prefer using `Set.isDisjoint(with:)` over `Set.intersection(_:).isEmpty`", + "parameters" : [ ] +}, { + "patternId" : "joined_default_parameter", + "title" : "Joined Default Parameter", + "description" : "Discouraged explicit usage of the default separator", + "parameters" : [ ] +}, { + "patternId" : "large_tuple", + "title" : "Large Tuple", + "description" : "Tuples shouldn't have too many members. Create a custom type instead.", + "parameters" : [ ] +}, { + "patternId" : "last_where", + "title" : "Last Where", + "description" : "Prefer using `.last(where:)` over `.filter { }.last` in collections", + "parameters" : [ ] +}, { + "patternId" : "leading_whitespace", + "title" : "Leading Whitespace", + "description" : "Files should not contain leading whitespace", + "parameters" : [ ] +}, { + "patternId" : "legacy_cggeometry_functions", + "title" : "Legacy CGGeometry Functions", + "description" : "Struct extension properties and methods are preferred over legacy functions", + "parameters" : [ ] +}, { + "patternId" : "legacy_constant", + "title" : "Legacy Constant", + "description" : "Struct-scoped constants are preferred over legacy global constants", + "parameters" : [ ] +}, { + "patternId" : "legacy_constructor", + "title" : "Legacy Constructor", + "description" : "Swift constructors are preferred over legacy convenience functions", + "parameters" : [ ] +}, { + "patternId" : "legacy_hashing", + "title" : "Legacy Hashing", + "description" : "Prefer using the `hash(into:)` function instead of overriding `hashValue`", + "parameters" : [ ] +}, { + "patternId" : "legacy_multiple", + "title" : "Legacy Multiple", + "description" : "Prefer using the `isMultiple(of:)` function instead of using the remainder operator (`%`)", + "parameters" : [ ] +}, { + "patternId" : "legacy_nsgeometry_functions", + "title" : "Legacy NSGeometry Functions", + "description" : "Struct extension properties and methods are preferred over legacy functions", + "parameters" : [ ] +}, { + "patternId" : "legacy_objc_type", + "title" : "Legacy Objective-C Reference Type", + "description" : "Prefer Swift value types to bridged Objective-C reference types", + "parameters" : [ ] +}, { + "patternId" : "legacy_random", + "title" : "Legacy Random", + "description" : "Prefer using `type.random(in:)` over legacy functions", + "parameters" : [ ] +}, { + "patternId" : "let_var_whitespace", + "title" : "Variable Declaration Whitespace", + "description" : "Variable declarations should be separated from other statements by a blank line", + "parameters" : [ ] +}, { + "patternId" : "line_length", + "title" : "Line Length", + "description" : "Lines should not span too many characters.", + "parameters" : [ ] +}, { + "patternId" : "literal_expression_end_indentation", + "title" : "Literal Expression End Indentation", + "description" : "Array and dictionary literal end should have the same indentation as the line that started it", + "parameters" : [ ] +}, { + "patternId" : "local_doc_comment", + "title" : "Local Doc Comment", + "description" : "Prefer regular comments over doc comments in local scopes", + "parameters" : [ ] +}, { + "patternId" : "lower_acl_than_parent", + "title" : "Lower ACL than Parent", + "description" : "Ensure declarations have a lower access control level than their enclosing parent", + "parameters" : [ ] +}, { + "patternId" : "mark", + "title" : "Mark", + "description" : "MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'", + "parameters" : [ ] +}, { + "patternId" : "missing_docs", + "title" : "Missing Docs", + "description" : "Declarations should be documented.", + "parameters" : [ ] +}, { + "patternId" : "modifier_order", + "title" : "Modifier Order", + "description" : "Modifier order should be consistent.", + "parameters" : [ ] +}, { + "patternId" : "multiline_arguments", + "title" : "Multiline Arguments", + "description" : "Arguments should be either on the same line, or one per line", + "parameters" : [ ] +}, { + "patternId" : "multiline_arguments_brackets", + "title" : "Multiline Arguments Brackets", + "description" : "Multiline arguments should have their surrounding brackets in a new line", + "parameters" : [ ] +}, { + "patternId" : "multiline_function_chains", + "title" : "Multiline Function Chains", + "description" : "Chained function calls should be either on the same line, or one per line", + "parameters" : [ ] +}, { + "patternId" : "multiline_literal_brackets", + "title" : "Multiline Literal Brackets", + "description" : "Multiline literals should have their surrounding brackets in a new line", + "parameters" : [ ] +}, { + "patternId" : "multiline_parameters", + "title" : "Multiline Parameters", + "description" : "Functions and methods parameters should be either on the same line, or one per line", + "parameters" : [ ] +}, { + "patternId" : "multiline_parameters_brackets", + "title" : "Multiline Parameters Brackets", + "description" : "Multiline parameters should have their surrounding brackets in a new line", + "parameters" : [ ] +}, { + "patternId" : "multiple_closures_with_trailing_closure", + "title" : "Multiple Closures with Trailing Closure", + "description" : "Trailing closure syntax should not be used when passing more than one closure argument", + "parameters" : [ ] +}, { + "patternId" : "nesting", + "title" : "Nesting", + "description" : "Types should be nested at most 1 level deep, and functions should be nested at most 2 levels deep.", + "parameters" : [ ] +}, { + "patternId" : "nimble_operator", + "title" : "Nimble Operator", + "description" : "Prefer Nimble operator overloads over free matcher functions", + "parameters" : [ ] +}, { + "patternId" : "no_empty_block", + "title" : "No Empty Block", + "description" : "Code blocks should contain at least one statement or comment", + "parameters" : [ ] +}, { + "patternId" : "no_extension_access_modifier", + "title" : "No Extension Access Modifier", + "description" : "Prefer not to use extension access modifiers", + "parameters" : [ ] +}, { + "patternId" : "no_fallthrough_only", + "title" : "No Fallthrough only", + "description" : "Fallthroughs can only be used if the `case` contains at least one other statement", + "parameters" : [ ] +}, { + "patternId" : "no_grouping_extension", + "title" : "No Grouping Extension", + "description" : "Extensions shouldn't be used to group code within the same source file", + "parameters" : [ ] +}, { + "patternId" : "no_magic_numbers", + "title" : "No Magic Numbers", + "description" : "Magic numbers should be replaced by named constants", + "parameters" : [ ] +}, { + "patternId" : "no_space_in_method_call", + "title" : "No Space in Method Call", + "description" : "Don't add a space between the method name and the parentheses", + "parameters" : [ ] +}, { + "patternId" : "non_optional_string_data_conversion", + "title" : "Non-optional String -> Data Conversion", + "description" : "Prefer non-optional `Data(_:)` initializer when converting `String` to `Data`", + "parameters" : [ ] +}, { + "patternId" : "non_overridable_class_declaration", + "title" : "Class Declaration in Final Class", + "description" : "Class methods and properties in final classes should themselves be final, just as if the declarations", + "parameters" : [ ] +}, { + "patternId" : "notification_center_detachment", + "title" : "Notification Center Detachment", + "description" : "An object should only remove itself as an observer in `deinit`", + "parameters" : [ ] +}, { + "patternId" : "ns_number_init_as_function_reference", + "title" : "NSNumber Init as Function Reference", + "description" : "Passing `NSNumber.init` or `NSDecimalNumber.init` as a function reference is dangerous as it can cause the wrong initializer to be used, causing crashes; use `.init(value:)` instead", + "parameters" : [ ] +}, { + "patternId" : "nslocalizedstring_key", + "title" : "NSLocalizedString Key", + "description" : "Static strings should be used as key/comment in NSLocalizedString in order for genstrings to work", + "parameters" : [ ] +}, { + "patternId" : "nslocalizedstring_require_bundle", + "title" : "NSLocalizedString Require Bundle", + "description" : "Calls to NSLocalizedString should specify the bundle which contains the strings file", + "parameters" : [ ] +}, { + "patternId" : "nsobject_prefer_isequal", + "title" : "NSObject Prefer isEqual", + "description" : "NSObject subclasses should implement isEqual instead of ==", + "parameters" : [ ] +}, { + "patternId" : "number_separator", + "title" : "Number Separator", + "description" : "Underscores should be used as thousand separator in large numbers with a configurable number of digits. In other words, there should be an underscore after every 3 digits in the integral as well as the fractional part of a number.", + "parameters" : [ ] +}, { + "patternId" : "object_literal", + "title" : "Object Literal", + "description" : "Prefer object literals over image and color inits", + "parameters" : [ ] +}, { + "patternId" : "one_declaration_per_file", + "title" : "One Declaration per File", + "description" : "Only a single declaration is allowed in a file", + "parameters" : [ ] +}, { + "patternId" : "opening_brace", + "title" : "Opening Brace Spacing", + "description" : "The correct positioning of braces that introduce a block of code or member list is highly controversial. No matter which style is preferred, consistency is key. Apart from different tastes, the positioning of braces can also have a significant impact on the readability of the code, especially for visually impaired developers. This rule ensures that braces are preceded by a single space and on the same line as the declaration. Comments between the declaration and the opening brace are respected.", + "parameters" : [ ] +}, { + "patternId" : "operator_usage_whitespace", + "title" : "Operator Usage Whitespace", + "description" : "Operators should be surrounded by a single whitespace when they are being used", + "parameters" : [ ] +}, { + "patternId" : "operator_whitespace", + "title" : "Operator Function Whitespace", + "description" : "Operators should be surrounded by a single whitespace when defining them", + "parameters" : [ ] +}, { + "patternId" : "optional_data_string_conversion", + "title" : "Optional Data -> String Conversion", + "description" : "Prefer failable `String(bytes:encoding:)` initializer when converting `Data` to `String`", + "parameters" : [ ] +}, { + "patternId" : "optional_enum_case_matching", + "title" : "Optional Enum Case Match", + "description" : "Matching an enum case against an optional enum without '?' is supported on Swift 5.1 and above", + "parameters" : [ ] +}, { + "patternId" : "orphaned_doc_comment", + "title" : "Orphaned Doc Comment", + "description" : "A doc comment should be attached to a declaration", + "parameters" : [ ] +}, { + "patternId" : "overridden_super_call", + "title" : "Overridden Method Calls Super", + "description" : "Some overridden methods should always call super.", + "parameters" : [ ] +}, { + "patternId" : "override_in_extension", + "title" : "Override in Extension", + "description" : "Extensions shouldn't override declarations", + "parameters" : [ ] +}, { + "patternId" : "pattern_matching_keywords", + "title" : "Pattern Matching Keywords", + "description" : "Combine multiple pattern matching bindings by moving keywords out of tuples", + "parameters" : [ ] +}, { + "patternId" : "period_spacing", + "title" : "Period Spacing", + "description" : "Periods should not be followed by more than one space", + "parameters" : [ ] +}, { + "patternId" : "prefer_key_path", + "title" : "Prefer Key Path", + "description" : "Use a key path argument instead of a closure with property access", + "parameters" : [ ] +}, { + "patternId" : "prefer_nimble", + "title" : "Prefer Nimble", + "description" : "Prefer Nimble matchers over XCTAssert functions", + "parameters" : [ ] +}, { + "patternId" : "prefer_self_in_static_references", + "title" : "Prefer Self in Static References", + "description" : "Use `Self` to refer to the surrounding type name", + "parameters" : [ ] +}, { + "patternId" : "prefer_self_type_over_type_of_self", + "title" : "Prefer Self Type Over Type of Self", + "description" : "Prefer `Self` over `type(of: self)` when accessing properties or calling methods", + "parameters" : [ ] +}, { + "patternId" : "prefer_type_checking", + "title" : "Prefer Type Checking", + "description" : "Prefer `a is X` to `a as? X != nil`", + "parameters" : [ ] +}, { + "patternId" : "prefer_zero_over_explicit_init", + "title" : "Prefer Zero Over Explicit Init", + "description" : "Prefer `.zero` over explicit init with zero parameters (e.g. `CGPoint(x: 0, y: 0)`)", + "parameters" : [ ] +}, { + "patternId" : "prefixed_toplevel_constant", + "title" : "Prefixed Top-Level Constant", + "description" : "Top-level constants should be prefixed by `k`", + "parameters" : [ ] +}, { + "patternId" : "private_action", + "title" : "Private Actions", + "description" : "IBActions should be private", + "parameters" : [ ] +}, { + "patternId" : "private_outlet", + "title" : "Private Outlets", + "description" : "IBOutlets should be private to avoid leaking UIKit to higher layers", + "parameters" : [ ] +}, { + "patternId" : "private_over_fileprivate", + "title" : "Private over Fileprivate", + "description" : "Prefer `private` over `fileprivate` declarations", + "parameters" : [ ] +}, { + "patternId" : "private_subject", + "title" : "Private Combine Subject", + "description" : "Combine Subject should be private", + "parameters" : [ ] +}, { + "patternId" : "private_swiftui_state", + "title" : "Private SwiftUI State Properties", + "description" : "SwiftUI state properties should be private", + "parameters" : [ ] +}, { + "patternId" : "private_unit_test", + "title" : "Private Unit Test", + "description" : "Unit tests marked private are silently skipped", + "parameters" : [ ] +}, { + "patternId" : "prohibited_interface_builder", + "title" : "Prohibited Interface Builder", + "description" : "Creating views using Interface Builder should be avoided", + "parameters" : [ ] +}, { + "patternId" : "prohibited_super_call", + "title" : "Prohibited Calls to Super", + "description" : "Some methods should not call super.", + "parameters" : [ ] +}, { + "patternId" : "protocol_property_accessors_order", + "title" : "Protocol Property Accessors Order", + "description" : "When declaring properties in protocols, the order of accessors should be `get set`", + "parameters" : [ ] +}, { + "patternId" : "quick_discouraged_call", + "title" : "Quick Discouraged Call", + "description" : "Discouraged call inside 'describe' and/or 'context' block.", + "parameters" : [ ] +}, { + "patternId" : "quick_discouraged_focused_test", + "title" : "Quick Discouraged Focused Test", + "description" : "Non-focused tests won't run as long as this test is focused", + "parameters" : [ ] +}, { + "patternId" : "quick_discouraged_pending_test", + "title" : "Quick Discouraged Pending Test", + "description" : "This test won't run as long as it's marked pending", + "parameters" : [ ] +}, { + "patternId" : "raw_value_for_camel_cased_codable_enum", + "title" : "Raw Value for Camel Cased Codable Enum", + "description" : "Camel cased cases of Codable String enums should have raw values", + "parameters" : [ ] +}, { + "patternId" : "reduce_boolean", + "title" : "Reduce Boolean", + "description" : "Prefer using `.allSatisfy()` or `.contains()` over `reduce(true)` or `reduce(false)`.", + "parameters" : [ ] +}, { + "patternId" : "reduce_into", + "title" : "Reduce into", + "description" : "Prefer `reduce(into:_:)` over `reduce(_:_:)` for copy-on-write types", + "parameters" : [ ] +}, { + "patternId" : "redundant_discardable_let", + "title" : "Redundant Discardable Let", + "description" : "Prefer `_ = foo()` over `let _ = foo()` when discarding a result from a function", + "parameters" : [ ] +}, { + "patternId" : "redundant_nil_coalescing", + "title" : "Redundant Nil Coalescing", + "description" : "nil coalescing operator is only evaluated if the lhs is nil, coalescing operator with nil as rhs is redundant", + "parameters" : [ ] +}, { + "patternId" : "redundant_objc_attribute", + "title" : "Redundant @objc Attribute", + "description" : "Objective-C attribute (@objc) is redundant in declaration", + "parameters" : [ ] +}, { + "patternId" : "redundant_optional_initialization", + "title" : "Redundant Optional Initialization", + "description" : "Initializing an optional variable with nil is redundant", + "parameters" : [ ] +}, { + "patternId" : "redundant_self_in_closure", + "title" : "Redundant Self in Closure", + "description" : "Explicit use of 'self' is not required", + "parameters" : [ ] +}, { + "patternId" : "redundant_sendable", + "title" : "Redundant Sendable", + "description" : "Sendable conformance is redundant on an actor-isolated type", + "parameters" : [ ] +}, { + "patternId" : "redundant_set_access_control", + "title" : "Redundant Access Control for Setter", + "description" : "Property setter access level shouldn't be explicit if it's the same as the variable access level", + "parameters" : [ ] +}, { + "patternId" : "redundant_string_enum_value", + "title" : "Redundant String Enum Value", + "description" : "String enum values can be omitted when they are equal to the enumcase name", + "parameters" : [ ] +}, { + "patternId" : "redundant_type_annotation", + "title" : "Redundant Type Annotation", + "description" : "Variables should not have redundant type annotation", + "parameters" : [ ] +}, { + "patternId" : "redundant_void_return", + "title" : "Redundant Void Return", + "description" : "Returning Void in a function declaration is redundant", + "parameters" : [ ] +}, { + "patternId" : "required_deinit", + "title" : "Required Deinit", + "description" : "Classes should have an explicit deinit method", + "parameters" : [ ] +}, { + "patternId" : "required_enum_case", + "title" : "Required Enum Case", + "description" : "Enums conforming to a specified protocol must implement a specific case(s).", + "parameters" : [ ] +}, { + "patternId" : "return_arrow_whitespace", + "title" : "Returning Whitespace", + "description" : "Return arrow and return type should be separated by a single space or on a separate line", + "parameters" : [ ] +}, { + "patternId" : "return_value_from_void_function", + "title" : "Return Value from Void Function", + "description" : "Returning values from Void functions should be avoided", + "parameters" : [ ] +}, { + "patternId" : "self_binding", + "title" : "Self Binding", + "description" : "Re-bind `self` to a consistent identifier name.", + "parameters" : [ ] +}, { + "patternId" : "self_in_property_initialization", + "title" : "Self in Property Initialization", + "description" : "`self` refers to the unapplied `NSObject.self()` method, which is likely not expected; make the variable `lazy` to be able to refer to the current instance or use `ClassName.self`", + "parameters" : [ ] +}, { + "patternId" : "shorthand_argument", + "title" : "Shorthand Argument", + "description" : "Shorthand arguments like `$0`, `$1`, etc. in closures can be confusing. Avoid using them too far away from the beginning of the closure. Optionally, while usage of a single shorthand argument is okay, more than one or complex ones with field accesses might increase the risk of obfuscation.", + "parameters" : [ ] +}, { + "patternId" : "shorthand_operator", + "title" : "Shorthand Operator", + "description" : "Prefer shorthand operators (+=, -=, *=, /=) over doing the operation and assigning", + "parameters" : [ ] +}, { + "patternId" : "shorthand_optional_binding", + "title" : "Shorthand Optional Binding", + "description" : "Use shorthand syntax for optional binding", + "parameters" : [ ] +}, { + "patternId" : "single_test_class", + "title" : "Single Test Class", + "description" : "Test files should contain a single QuickSpec or XCTestCase class.", + "parameters" : [ ] +}, { + "patternId" : "sorted_enum_cases", + "title" : "Sorted Enum Cases", + "description" : "Enum cases should be sorted", + "parameters" : [ ] +}, { + "patternId" : "sorted_first_last", + "title" : "Min or Max over Sorted First or Last", + "description" : "Prefer using `min()` or `max()` over `sorted().first` or `sorted().last`", + "parameters" : [ ] +}, { + "patternId" : "sorted_imports", + "title" : "Sorted Imports", + "description" : "Imports should be sorted", + "parameters" : [ ] +}, { + "patternId" : "statement_position", + "title" : "Statement Position", + "description" : "Else and catch should be on the same line, one space after the previous declaration", + "parameters" : [ ] +}, { + "patternId" : "static_operator", + "title" : "Static Operator", + "description" : "Operators should be declared as static functions, not free functions", + "parameters" : [ ] +}, { + "patternId" : "static_over_final_class", + "title" : "Static Over Final Class", + "description" : "Prefer `static` over `class` when the declaration is not allowed to be overridden in child classes due to its context being final. Likewise, the compiler complains about `open` being used in `final` classes.", + "parameters" : [ ] +}, { + "patternId" : "strict_fileprivate", + "title" : "Strict Fileprivate", + "description" : "`fileprivate` should be avoided", + "parameters" : [ ] +}, { + "patternId" : "strong_iboutlet", + "title" : "Strong IBOutlet", + "description" : "@IBOutlets shouldn't be declared as weak", + "parameters" : [ ] +}, { + "patternId" : "superfluous_disable_command", + "title" : "Superfluous Disable Command", + "description" : "SwiftLint 'disable' commands are superfluous when the disabled rule would not have triggered a violation in the disabled region. Use \" - \" if you wish to document a command.", + "parameters" : [ ] +}, { + "patternId" : "superfluous_else", + "title" : "Superfluous Else", + "description" : "Else branches should be avoided when the previous if-block exits the current scope", + "parameters" : [ ] +}, { + "patternId" : "switch_case_alignment", + "title" : "Switch and Case Statement Alignment", + "description" : "Case statements should vertically align with their closing brace, or indented if configured otherwise.", + "parameters" : [ ] +}, { + "patternId" : "switch_case_on_newline", + "title" : "Cases on Newline", + "description" : "Cases inside a switch should always be on a newline", + "parameters" : [ ] +}, { + "patternId" : "syntactic_sugar", + "title" : "Syntactic Sugar", + "description" : "Shorthand syntactic sugar should be used, i.e. [Int] instead of Array.", + "parameters" : [ ] +}, { + "patternId" : "test_case_accessibility", + "title" : "Test Case Accessibility", + "description" : "Test cases should only contain private non-test members", + "parameters" : [ ] +}, { + "patternId" : "todo", + "title" : "Todo", + "description" : "TODOs and FIXMEs should be resolved.", + "parameters" : [ ] +}, { + "patternId" : "toggle_bool", + "title" : "Toggle Bool", + "description" : "Prefer `someBool.toggle()` over `someBool = !someBool`", + "parameters" : [ ] +}, { + "patternId" : "trailing_closure", + "title" : "Trailing Closure", + "description" : "Trailing closure syntax should be used whenever possible", + "parameters" : [ ] +}, { + "patternId" : "trailing_comma", + "title" : "Trailing Comma", + "description" : "Trailing commas in arrays and dictionaries should be avoided/enforced.", + "parameters" : [ ] +}, { + "patternId" : "trailing_newline", + "title" : "Trailing Newline", + "description" : "Files should have a single trailing newline", + "parameters" : [ ] +}, { + "patternId" : "trailing_semicolon", + "title" : "Trailing Semicolon", + "description" : "Lines should not have trailing semicolons", + "parameters" : [ ] +}, { + "patternId" : "trailing_whitespace", + "title" : "Trailing Whitespace", + "description" : "Lines should not have trailing whitespace", + "parameters" : [ ] +}, { + "patternId" : "type_body_length", + "title" : "Type Body Length", + "description" : "Type bodies should not span too many lines", + "parameters" : [ ] +}, { + "patternId" : "type_contents_order", + "title" : "Type Contents Order", + "description" : "Specifies the order of subtypes, properties, methods & more within a type.", + "parameters" : [ ] +}, { + "patternId" : "type_name", + "title" : "Type Name", + "description" : "Type name should only contain alphanumeric characters, start with an uppercase character and span between 3 and 40 characters in length.", + "parameters" : [ ] +}, { + "patternId" : "typesafe_array_init", + "title" : "Type-safe Array Init", + "description" : "Prefer using `Array(seq)` over `seq.map { $0 }` to convert a sequence into an Array", + "parameters" : [ ] +}, { + "patternId" : "unavailable_condition", + "title" : "Unavailable Condition", + "description" : "Use #unavailable/#available instead of #available/#unavailable with an empty body.", + "parameters" : [ ] +}, { + "patternId" : "unavailable_function", + "title" : "Unavailable Function", + "description" : "Unimplemented functions should be marked as unavailable", + "parameters" : [ ] +}, { + "patternId" : "unhandled_throwing_task", + "title" : "Unhandled Throwing Task", + "description" : "Errors thrown inside this task are not handled, which may be unexpected. Handle errors inside the task, or use `try await` to access the Tasks value and handle errors. See this forum thread for more details: https://forums.swift.org/t/task-initializer-with-throwing-closure-swallows-error/56066", + "parameters" : [ ] +}, { + "patternId" : "unneeded_break_in_switch", + "title" : "Unneeded Break in Switch", + "description" : "Avoid using unneeded break statements", + "parameters" : [ ] +}, { + "patternId" : "unneeded_override", + "title" : "Unneeded Overridden Functions", + "description" : "Remove overridden functions that don't do anything except call their super", + "parameters" : [ ] +}, { + "patternId" : "unneeded_parentheses_in_closure_argument", + "title" : "Unneeded Parentheses in Closure Argument", + "description" : "Parentheses are not needed when declaring closure arguments", + "parameters" : [ ] +}, { + "patternId" : "unneeded_synthesized_initializer", + "title" : "Unneeded Synthesized Initializer", + "description" : "Default or memberwise initializers that will be automatically synthesized do not need to be manually defined.", + "parameters" : [ ] +}, { + "patternId" : "unowned_variable_capture", + "title" : "Unowned Variable Capture", + "description" : "Prefer capturing references as weak to avoid potential crashes", + "parameters" : [ ] +}, { + "patternId" : "untyped_error_in_catch", + "title" : "Untyped Error in Catch", + "description" : "Catch statements should not declare error variables without type casting", + "parameters" : [ ] +}, { + "patternId" : "unused_closure_parameter", + "title" : "Unused Closure Parameter", + "description" : "Unused parameter in a closure should be replaced with _", + "parameters" : [ ] +}, { + "patternId" : "unused_control_flow_label", + "title" : "Unused Control Flow Label", + "description" : "Unused control flow label should be removed", + "parameters" : [ ] +}, { + "patternId" : "unused_declaration", + "title" : "Unused Declaration", + "description" : "Declarations should be referenced at least once within all files linted", + "parameters" : [ ] +}, { + "patternId" : "unused_enumerated", + "title" : "Unused Enumerated", + "description" : "When the index or the item is not used, `.enumerated()` can be removed.", + "parameters" : [ ] +}, { + "patternId" : "unused_import", + "title" : "Unused Import", + "description" : "All imported modules should be required to make the file compile", + "parameters" : [ ] +}, { + "patternId" : "unused_optional_binding", + "title" : "Unused Optional Binding", + "description" : "Prefer `!= nil` over `let _ =`", + "parameters" : [ ] +}, { + "patternId" : "unused_parameter", + "title" : "Unused Parameter", + "description" : "Other than unused local variable declarations, unused function/initializer/subscript parameters are not marked by the Swift compiler. Since unused parameters are code smells, they should either be removed or replaced/shadowed by a wildcard '_' to indicate that they are being deliberately disregarded.", + "parameters" : [ ] +}, { + "patternId" : "unused_setter_value", + "title" : "Unused Setter Value", + "description" : "Setter value is not used", + "parameters" : [ ] +}, { + "patternId" : "valid_ibinspectable", + "title" : "Valid IBInspectable", + "description" : "@IBInspectable should be applied to variables only, have its type explicit and be of a supported type", + "parameters" : [ ] +}, { + "patternId" : "vertical_parameter_alignment", + "title" : "Vertical Parameter Alignment", + "description" : "Function parameters should be aligned vertically if they're in multiple lines in a declaration", + "parameters" : [ ] +}, { + "patternId" : "vertical_parameter_alignment_on_call", + "title" : "Vertical Parameter Alignment on Call", + "description" : "Function parameters should be aligned vertically if they're in multiple lines in a method call", + "parameters" : [ ] +}, { + "patternId" : "vertical_whitespace", + "title" : "Vertical Whitespace", + "description" : "Limit vertical whitespace to a single empty line.", + "parameters" : [ ] +}, { + "patternId" : "vertical_whitespace_between_cases", + "title" : "Vertical Whitespace Between Cases", + "description" : "Include a single empty line between switch cases", + "parameters" : [ ] +}, { + "patternId" : "vertical_whitespace_closing_braces", + "title" : "Vertical Whitespace before Closing Braces", + "description" : "Don't include vertical whitespace (empty line) before closing braces", + "parameters" : [ ] +}, { + "patternId" : "vertical_whitespace_opening_braces", + "title" : "Vertical Whitespace after Opening Braces", + "description" : "Don't include vertical whitespace (empty line) after opening braces", + "parameters" : [ ] +}, { + "patternId" : "void_function_in_ternary", + "title" : "Void Function in Ternary", + "description" : "Using ternary to call Void functions should be avoided", + "parameters" : [ ] +}, { + "patternId" : "void_return", + "title" : "Void Return", + "description" : "Prefer `-> Void` over `-> ()`", + "parameters" : [ ] +}, { + "patternId" : "weak_delegate", + "title" : "Weak Delegate", + "description" : "Delegates should be weak to avoid reference cycles", + "parameters" : [ ] +}, { + "patternId" : "xct_specific_matcher", + "title" : "XCTest Specific Matcher", + "description" : "Prefer specific XCTest matchers over `XCTAssertEqual` and `XCTAssertNotEqual`.", + "parameters" : [ ] +}, { + "patternId" : "xctfail_message", + "title" : "XCTFail Message", + "description" : "An XCTFail call should include a description of the assertion", + "parameters" : [ ] +}, { + "patternId" : "yoda_condition", + "title" : "Yoda Condition", + "description" : "The constant literal should be placed on the right-hand side of the comparison operator", + "parameters" : [ ] +} ] diff --git a/docs/description/direct_return.md b/docs/description/direct_return.md new file mode 100644 index 0000000..3708323 --- /dev/null +++ b/docs/description/direct_return.md @@ -0,0 +1,110 @@ +# Direct Return + +Directly return the expression instead of assigning it to a variable first + +* **Identifier:** `direct_return` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func f() -> Int { + let b = 2 + let a = 1 + return b +} +``` + +```swift +struct S { + var a: Int { + var b = 1 + b = 2 + return b + } +} +``` + +```swift +func f() -> Int { + let b = 2 + f() + return b +} +``` + +```swift +func f() -> Int { + { i in + let b = 2 + return i + }(1) +} +``` + +## Triggering Examples + +```swift +func f() -> Int { + let ↓b = 2 + return b +} +``` + +```swift +struct S { + var a: Int { + var ↓b = 1 + // comment + return b + } +} +``` + +```swift +func f() -> Bool { + let a = 1, ↓b = true + return b +} +``` + +```swift +func f() -> Int { + { _ in + let ↓b = 2 + return b + }(1) +} +``` + +```swift +func f(i: Int) -> Int { + if i > 1 { + let ↓a = 2 + return a + } else { + let ↓b = 2, a = 1 + return b + } +} +``` \ No newline at end of file diff --git a/docs/description/discarded_notification_center_observer.md b/docs/description/discarded_notification_center_observer.md new file mode 100644 index 0000000..6d9e016 --- /dev/null +++ b/docs/description/discarded_notification_center_observer.md @@ -0,0 +1,132 @@ +# Discarded Notification Center Observer + +When registering for a notification using a block, the opaque observer that is returned should be stored so it can be removed later + +* **Identifier:** `discarded_notification_center_observer` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { } +``` + +```swift +let foo = nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }) +``` + +```swift +func foo() -> Any { + return nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }) +} +``` + +```swift +func foo() -> Any { + nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }) +} +``` + +```swift +var obs: [Any?] = [] +obs.append(nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })) +``` + +```swift +var obs: [String: Any?] = [] +obs["foo"] = nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }) +``` + +```swift +var obs: [Any?] = [] +obs.append(nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })) +``` + +```swift +func foo(_ notify: Any) { + obs.append(notify) +} +foo(nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })) +``` + +```swift +var obs: [NSObjectProtocol] = [ + nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }), + nc.addObserver(forName: .CKAccountChanged, object: nil, queue: nil, using: { }) +] +``` + +```swift +names.map { self.notificationCenter.addObserver(forName: $0, object: object, queue: queue, using: block) } +``` + +```swift +f { return nc.addObserver(forName: $0, object: object, queue: queue, using: block) } +``` + +## Triggering Examples + +```swift +↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { } +``` + +```swift +_ = ↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { } +``` + +```swift +↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }) +``` + +```swift +@discardableResult func foo() -> Any { + return ↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }) +} +``` + +```swift +class C { + var i: Int { + set { ↓notificationCenter.addObserver(forName: $0, object: object, queue: queue, using: block) } + get { + ↓notificationCenter.addObserver(forName: $0, object: object, queue: queue, using: block) + return 2 + } + } +} +``` + +```swift +f { + ↓nc.addObserver(forName: $0, object: object, queue: queue) {} + return 2 +} +``` + +```swift +func foo() -> Any { + if cond { + ↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { }) + } +} +``` \ No newline at end of file diff --git a/docs/description/discouraged_assert.md b/docs/description/discouraged_assert.md new file mode 100644 index 0000000..9461b72 --- /dev/null +++ b/docs/description/discouraged_assert.md @@ -0,0 +1,66 @@ +# Discouraged Assert + +Prefer `assertionFailure()` and/or `preconditionFailure()` over `assert(false)` + +* **Identifier:** `discouraged_assert` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +assert(true) +``` + +```swift +assert(true, "foobar") +``` + +```swift +assert(true, "foobar", file: "toto", line: 42) +``` + +```swift +assert(false || true) +``` + +```swift +XCTAssert(false) +``` + +## Triggering Examples + +```swift +↓assert(false) +``` + +```swift +↓assert(false, "foobar") +``` + +```swift +↓assert(false, "foobar", file: "toto", line: 42) +``` + +```swift +↓assert( false , "foobar") +``` \ No newline at end of file diff --git a/docs/description/discouraged_direct_init.md b/docs/description/discouraged_direct_init.md new file mode 100644 index 0000000..b17622b --- /dev/null +++ b/docs/description/discouraged_direct_init.md @@ -0,0 +1,122 @@ +# Discouraged Direct Initialization + +Discouraged direct initialization of types that can be harmful + +* **Identifier:** `discouraged_direct_init` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ types + + ["Bundle", "Bundle.init", "NSError", "NSError.init", "UIDevice", "UIDevice.init"] +
+ +## Non Triggering Examples + +```swift +let foo = UIDevice.current +``` + +```swift +let foo = Bundle.main +``` + +```swift +let foo = Bundle(path: "bar") +``` + +```swift +let foo = Bundle(identifier: "bar") +``` + +```swift +let foo = Bundle.init(path: "bar") +``` + +```swift +let foo = Bundle.init(identifier: "bar") +``` + +```swift +let foo = NSError(domain: "bar", code: 0) +``` + +```swift +let foo = NSError.init(domain: "bar", code: 0) +``` + +```swift +func testNSError() +``` + +## Triggering Examples + +```swift +↓UIDevice() +``` + +```swift +↓Bundle() +``` + +```swift +let foo = ↓UIDevice() +``` + +```swift +let foo = ↓Bundle() +``` + +```swift +let foo = ↓NSError() +``` + +```swift +let foo = bar(bundle: ↓Bundle(), device: ↓UIDevice(), error: ↓NSError()) +``` + +```swift +↓UIDevice.init() +``` + +```swift +↓Bundle.init() +``` + +```swift +↓NSError.init() +``` + +```swift +let foo = ↓UIDevice.init() +``` + +```swift +let foo = ↓Bundle.init() +``` + +```swift +let foo = bar(bundle: ↓Bundle.init(), device: ↓UIDevice.init(), error: ↓NSError.init()) +``` \ No newline at end of file diff --git a/docs/description/discouraged_none_name.md b/docs/description/discouraged_none_name.md new file mode 100644 index 0000000..18eeb3d --- /dev/null +++ b/docs/description/discouraged_none_name.md @@ -0,0 +1,220 @@ +# Discouraged None Name + +Enum cases and static members named `none` are discouraged as they can conflict with `Optional.none`. + +* **Identifier:** `discouraged_none_name` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +enum MyEnum { + case nOne +} +``` + +```swift +enum MyEnum { + case _none +} +``` + +```swift +enum MyEnum { + case none_ +} +``` + +```swift +enum MyEnum { + case none(Any) +} +``` + +```swift +enum MyEnum { + case nonenone +} +``` + +```swift +class MyClass { + class var nonenone: MyClass { MyClass() } +} +``` + +```swift +class MyClass { + static var nonenone = MyClass() +} +``` + +```swift +class MyClass { + static let nonenone = MyClass() +} +``` + +```swift +struct MyStruct { + static var nonenone = MyStruct() +} +``` + +```swift +struct MyStruct { + static let nonenone = MyStruct() +} +``` + +```swift +struct MyStruct { + let none = MyStruct() +} +``` + +```swift +struct MyStruct { + var none = MyStruct() +} +``` + +```swift +class MyClass { + let none = MyClass() +} +``` + +```swift +class MyClass { + var none = MyClass() +} +``` + +## Triggering Examples + +```swift +enum MyEnum { + case ↓none +} +``` + +```swift +enum MyEnum { + case a, ↓none +} +``` + +```swift +enum MyEnum { + case ↓none, b +} +``` + +```swift +enum MyEnum { + case a, ↓none, b +} +``` + +```swift +enum MyEnum { + case a + case ↓none +} +``` + +```swift +enum MyEnum { + case ↓none + case b +} +``` + +```swift +enum MyEnum { + case a + case ↓none + case b +} +``` + +```swift +class MyClass { + ↓static let none = MyClass() +} +``` + +```swift +class MyClass { + ↓static let none: MyClass = MyClass() +} +``` + +```swift +class MyClass { + ↓static var none: MyClass = MyClass() +} +``` + +```swift +class MyClass { + ↓class var none: MyClass { MyClass() } +} +``` + +```swift +struct MyStruct { + ↓static var none = MyStruct() +} +``` + +```swift +struct MyStruct { + ↓static var none: MyStruct = MyStruct() +} +``` + +```swift +struct MyStruct { + ↓static var none = MyStruct() +} +``` + +```swift +struct MyStruct { + ↓static var none: MyStruct = MyStruct() +} +``` + +```swift +struct MyStruct { + ↓static var a = MyStruct(), none = MyStruct() +} +``` + +```swift +struct MyStruct { + ↓static var none = MyStruct(), a = MyStruct() +} +``` \ No newline at end of file diff --git a/docs/description/discouraged_object_literal.md b/docs/description/discouraged_object_literal.md new file mode 100644 index 0000000..8a6a5e9 --- /dev/null +++ b/docs/description/discouraged_object_literal.md @@ -0,0 +1,78 @@ +# Discouraged Object Literal + +Prefer initializers over object literals + +* **Identifier:** `discouraged_object_literal` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ image_literal + + true +
+ color_literal + + true +
+ +## Non Triggering Examples + +```swift +let image = UIImage(named: aVariable) +``` + +```swift +let image = UIImage(named: "interpolated \(variable)") +``` + +```swift +let color = UIColor(red: value, green: value, blue: value, alpha: 1) +``` + +```swift +let image = NSImage(named: aVariable) +``` + +```swift +let image = NSImage(named: "interpolated \(variable)") +``` + +```swift +let color = NSColor(red: value, green: value, blue: value, alpha: 1) +``` + +## Triggering Examples + +```swift +let image = ↓#imageLiteral(resourceName: "image.jpg") +``` + +```swift +let color = ↓#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1) +``` \ No newline at end of file diff --git a/docs/description/discouraged_optional_boolean.md b/docs/description/discouraged_optional_boolean.md new file mode 100644 index 0000000..34f6aa5 --- /dev/null +++ b/docs/description/discouraged_optional_boolean.md @@ -0,0 +1,646 @@ +# Discouraged Optional Boolean + +Prefer non-optional booleans over optional booleans + +* **Identifier:** `discouraged_optional_boolean` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +var foo: Bool +``` + +```swift +var foo: [String: Bool] +``` + +```swift +var foo: [Bool] +``` + +```swift +let foo: Bool = true +``` + +```swift +let foo: Bool = false +``` + +```swift +let foo: [String: Bool] = [:] +``` + +```swift +let foo: [Bool] = [] +``` + +```swift +var foo: Bool { return true } +``` + +```swift +let foo: Bool { return false }() +``` + +```swift +func foo() -> Bool {} +``` + +```swift +func foo() -> [String: Bool] {} +``` + +```swift +func foo() -> ([Bool]) -> String {} +``` + +```swift +func foo(input: Bool = true) {} +``` + +```swift +func foo(input: [String: Bool] = [:]) {} +``` + +```swift +func foo(input: [Bool] = []) {} +``` + +```swift +class Foo { + func foo() -> Bool {} +} +``` + +```swift +class Foo { + func foo() -> [String: Bool] {} +} +``` + +```swift +class Foo { + func foo() -> ([Bool]) -> String {} +} +``` + +```swift +struct Foo { + func foo() -> Bool {} +} +``` + +```swift +struct Foo { + func foo() -> [String: Bool] {} +} +``` + +```swift +struct Foo { + func foo() -> ([Bool]) -> String {} +} +``` + +```swift +enum Foo { + func foo() -> Bool {} +} +``` + +```swift +enum Foo { + func foo() -> [String: Bool] {} +} +``` + +```swift +enum Foo { + func foo() -> ([Bool]) -> String {} +} +``` + +```swift +class Foo { + func foo(input: Bool = true) {} +} +``` + +```swift +class Foo { + func foo(input: [String: Bool] = [:]) {} +} +``` + +```swift +class Foo { + func foo(input: [Bool] = []) {} +} +``` + +```swift +struct Foo { + func foo(input: Bool = true) {} +} +``` + +```swift +struct Foo { + func foo(input: [String: Bool] = [:]) {} +} +``` + +```swift +struct Foo { + func foo(input: [Bool] = []) {} +} +``` + +```swift +enum Foo { + func foo(input: Bool = true) {} +} +``` + +```swift +enum Foo { + func foo(input: [String: Bool] = [:]) {} +} +``` + +```swift +enum Foo { + func foo(input: [Bool] = []) {} +} +``` + +## Triggering Examples + +```swift +var foo: ↓Bool? +``` + +```swift +var foo: [String: ↓Bool?] +``` + +```swift +var foo: [↓Bool?] +``` + +```swift +let foo: ↓Bool? = nil +``` + +```swift +let foo: [String: ↓Bool?] = [:] +``` + +```swift +let foo: [↓Bool?] = [] +``` + +```swift +let foo = ↓Optional.some(false) +``` + +```swift +let foo = ↓Optional.some(true) +``` + +```swift +var foo: ↓Bool? { return nil } +``` + +```swift +let foo: ↓Bool? { return nil }() +``` + +```swift +func foo() -> ↓Bool? {} +``` + +```swift +func foo() -> [String: ↓Bool?] {} +``` + +```swift +func foo() -> [↓Bool?] {} +``` + +```swift +static func foo() -> ↓Bool? {} +``` + +```swift +static func foo() -> [String: ↓Bool?] {} +``` + +```swift +static func foo() -> [↓Bool?] {} +``` + +```swift +func foo() -> (↓Bool?) -> String {} +``` + +```swift +func foo() -> ([Int]) -> ↓Bool? {} +``` + +```swift +func foo(input: ↓Bool?) {} +``` + +```swift +func foo(input: [String: ↓Bool?]) {} +``` + +```swift +func foo(input: [↓Bool?]) {} +``` + +```swift +static func foo(input: ↓Bool?) {} +``` + +```swift +static func foo(input: [String: ↓Bool?]) {} +``` + +```swift +static func foo(input: [↓Bool?]) {} +``` + +```swift +class Foo { + var foo: ↓Bool? +} +``` + +```swift +class Foo { + var foo: [String: ↓Bool?] +} +``` + +```swift +class Foo { + let foo: ↓Bool? = nil +} +``` + +```swift +class Foo { + let foo: [String: ↓Bool?] = [:] +} +``` + +```swift +class Foo { + let foo: [↓Bool?] = [] +} +``` + +```swift +struct Foo { + var foo: ↓Bool? +} +``` + +```swift +struct Foo { + var foo: [String: ↓Bool?] +} +``` + +```swift +struct Foo { + let foo: ↓Bool? = nil +} +``` + +```swift +struct Foo { + let foo: [String: ↓Bool?] = [:] +} +``` + +```swift +struct Foo { + let foo: [↓Bool?] = [] +} +``` + +```swift +class Foo { + var foo: ↓Bool? { return nil } +} +``` + +```swift +class Foo { + let foo: ↓Bool? { return nil }() +} +``` + +```swift +struct Foo { + var foo: ↓Bool? { return nil } +} +``` + +```swift +struct Foo { + let foo: ↓Bool? { return nil }() +} +``` + +```swift +enum Foo { + var foo: ↓Bool? { return nil } +} +``` + +```swift +enum Foo { + let foo: ↓Bool? { return nil }() +} +``` + +```swift +class Foo { + func foo() -> ↓Bool? {} +} +``` + +```swift +class Foo { + func foo() -> [String: ↓Bool?] {} +} +``` + +```swift +class Foo { + func foo() -> [↓Bool?] {} +} +``` + +```swift +class Foo { + static func foo() -> ↓Bool? {} +} +``` + +```swift +class Foo { + static func foo() -> [String: ↓Bool?] {} +} +``` + +```swift +class Foo { + static func foo() -> [↓Bool?] {} +} +``` + +```swift +class Foo { + func foo() -> (↓Bool?) -> String {} +} +``` + +```swift +class Foo { + func foo() -> ([Int]) -> ↓Bool? {} +} +``` + +```swift +struct Foo { + func foo() -> ↓Bool? {} +} +``` + +```swift +struct Foo { + func foo() -> [String: ↓Bool?] {} +} +``` + +```swift +struct Foo { + func foo() -> [↓Bool?] {} +} +``` + +```swift +struct Foo { + static func foo() -> ↓Bool? {} +} +``` + +```swift +struct Foo { + static func foo() -> [String: ↓Bool?] {} +} +``` + +```swift +struct Foo { + static func foo() -> [↓Bool?] {} +} +``` + +```swift +struct Foo { + func foo() -> (↓Bool?) -> String {} +} +``` + +```swift +struct Foo { + func foo() -> ([Int]) -> ↓Bool? {} +} +``` + +```swift +enum Foo { + func foo() -> ↓Bool? {} +} +``` + +```swift +enum Foo { + func foo() -> [String: ↓Bool?] {} +} +``` + +```swift +enum Foo { + func foo() -> [↓Bool?] {} +} +``` + +```swift +enum Foo { + static func foo() -> ↓Bool? {} +} +``` + +```swift +enum Foo { + static func foo() -> [String: ↓Bool?] {} +} +``` + +```swift +enum Foo { + static func foo() -> [↓Bool?] {} +} +``` + +```swift +enum Foo { + func foo() -> (↓Bool?) -> String {} +} +``` + +```swift +enum Foo { + func foo() -> ([Int]) -> ↓Bool? {} +} +``` + +```swift +class Foo { + func foo(input: ↓Bool?) {} +} +``` + +```swift +class Foo { + func foo(input: [String: ↓Bool?]) {} +} +``` + +```swift +class Foo { + func foo(input: [↓Bool?]) {} +} +``` + +```swift +class Foo { + static func foo(input: ↓Bool?) {} +} +``` + +```swift +class Foo { + static func foo(input: [String: ↓Bool?]) {} +} +``` + +```swift +class Foo { + static func foo(input: [↓Bool?]) {} +} +``` + +```swift +struct Foo { + func foo(input: ↓Bool?) {} +} +``` + +```swift +struct Foo { + func foo(input: [String: ↓Bool?]) {} +} +``` + +```swift +struct Foo { + func foo(input: [↓Bool?]) {} +} +``` + +```swift +struct Foo { + static func foo(input: ↓Bool?) {} +} +``` + +```swift +struct Foo { + static func foo(input: [String: ↓Bool?]) {} +} +``` + +```swift +struct Foo { + static func foo(input: [↓Bool?]) {} +} +``` + +```swift +enum Foo { + func foo(input: ↓Bool?) {} +} +``` + +```swift +enum Foo { + func foo(input: [String: ↓Bool?]) {} +} +``` + +```swift +enum Foo { + func foo(input: [↓Bool?]) {} +} +``` + +```swift +enum Foo { + static func foo(input: ↓Bool?) {} +} +``` + +```swift +enum Foo { + static func foo(input: [String: ↓Bool?]) {} +} +``` + +```swift +enum Foo { + static func foo(input: [↓Bool?]) {} +} +``` + +```swift +_ = ↓Bool?.values() +``` \ No newline at end of file diff --git a/docs/description/discouraged_optional_collection.md b/docs/description/discouraged_optional_collection.md new file mode 100644 index 0000000..a57fa03 --- /dev/null +++ b/docs/description/discouraged_optional_collection.md @@ -0,0 +1,924 @@ +# Discouraged Optional Collection + +Prefer empty collection over optional collection + +* **Identifier:** `discouraged_optional_collection` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +var foo: [Int] +``` + +```swift +var foo: [String: Int] +``` + +```swift +var foo: Set +``` + +```swift +var foo: [String: [String: Int]] +``` + +```swift +let foo: [Int] = [] +``` + +```swift +let foo: [String: Int] = [:] +``` + +```swift +let foo: Set = [] +``` + +```swift +let foo: [String: [String: Int]] = [:] +``` + +```swift +var foo: [Int] { return [] } +``` + +```swift +func foo() -> [Int] {} +``` + +```swift +func foo() -> [String: String] {} +``` + +```swift +func foo() -> Set {} +``` + +```swift +func foo() -> ([Int]) -> String {} +``` + +```swift +func foo(input: [String] = []) {} +``` + +```swift +func foo(input: [String: String] = [:]) {} +``` + +```swift +func foo(input: Set = []) {} +``` + +```swift +class Foo { + func foo() -> [Int] {} +} +``` + +```swift +class Foo { + func foo() -> [String: String] {} +} +``` + +```swift +class Foo { + func foo() -> Set {} +} +``` + +```swift +class Foo { + func foo() -> ([Int]) -> String {} +} +``` + +```swift +struct Foo { + func foo() -> [Int] {} +} +``` + +```swift +struct Foo { + func foo() -> [String: String] {} +} +``` + +```swift +struct Foo { + func foo() -> Set {} +} +``` + +```swift +struct Foo { + func foo() -> ([Int]) -> String {} +} +``` + +```swift +enum Foo { + func foo() -> [Int] {} +} +``` + +```swift +enum Foo { + func foo() -> [String: String] {} +} +``` + +```swift +enum Foo { + func foo() -> Set {} +} +``` + +```swift +enum Foo { + func foo() -> ([Int]) -> String {} +} +``` + +```swift +class Foo { + func foo(input: [String] = []) {} +} +``` + +```swift +class Foo { + func foo(input: [String: String] = [:]) {} +} +``` + +```swift +class Foo { + func foo(input: Set = []) {} +} +``` + +```swift +struct Foo { + func foo(input: [String] = []) {} +} +``` + +```swift +struct Foo { + func foo(input: [String: String] = [:]) {} +} +``` + +```swift +struct Foo { + func foo(input: Set = []) {} +} +``` + +```swift +enum Foo { + func foo(input: [String] = []) {} +} +``` + +```swift +enum Foo { + func foo(input: [String: String] = [:]) {} +} +``` + +```swift +enum Foo { + func foo(input: Set = []) {} +} +``` + +## Triggering Examples + +```swift +var foo: ↓[Int]? +``` + +```swift +var foo: ↓[String: Int]? +``` + +```swift +var foo: ↓Set? +``` + +```swift +let foo: ↓[Int]? = nil +``` + +```swift +let foo: ↓[String: Int]? = nil +``` + +```swift +let foo: ↓Set? = nil +``` + +```swift +var foo: ↓[Int]? { return nil } +``` + +```swift +let foo: ↓[Int]? { return nil }() +``` + +```swift +func foo() -> ↓[T]? {} +``` + +```swift +func foo() -> ↓[String: String]? {} +``` + +```swift +func foo() -> ↓[String: [String: String]]? {} +``` + +```swift +func foo() -> [String: ↓[String: String]?] {} +``` + +```swift +func foo() -> ↓Set? {} +``` + +```swift +static func foo() -> ↓[T]? {} +``` + +```swift +static func foo() -> ↓[String: String]? {} +``` + +```swift +static func foo() -> ↓[String: [String: String]]? {} +``` + +```swift +static func foo() -> [String: ↓[String: String]?] {} +``` + +```swift +static func foo() -> ↓Set? {} +``` + +```swift +func foo() -> (↓[Int]?) -> String {} +``` + +```swift +func foo() -> ([Int]) -> ↓[String]? {} +``` + +```swift +func foo(input: ↓[String: String]?) {} +``` + +```swift +func foo(input: ↓[String: [String: String]]?) {} +``` + +```swift +func foo(input: [String: ↓[String: String]?]) {} +``` + +```swift +func foo(input: ↓[String: ↓[String: String]?]?) {} +``` + +```swift +func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +``` + +```swift +func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +``` + +```swift +static func foo(input: ↓[String: String]?) {} +``` + +```swift +static func foo(input: ↓[String: [String: String]]?) {} +``` + +```swift +static func foo(input: [String: ↓[String: String]?]) {} +``` + +```swift +static func foo(input: ↓[String: ↓[String: String]?]?) {} +``` + +```swift +static func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +``` + +```swift +static func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +``` + +```swift +class Foo { + var foo: ↓[Int]? +} +``` + +```swift +class Foo { + var foo: ↓[String: Int]? +} +``` + +```swift +class Foo { + var foo: ↓Set? +} +``` + +```swift +class Foo { + let foo: ↓[Int]? = nil +} +``` + +```swift +class Foo { + let foo: ↓[String: Int]? = nil +} +``` + +```swift +class Foo { + let foo: ↓Set? = nil +} +``` + +```swift +struct Foo { + var foo: ↓[Int]? +} +``` + +```swift +struct Foo { + var foo: ↓[String: Int]? +} +``` + +```swift +struct Foo { + var foo: ↓Set? +} +``` + +```swift +struct Foo { + let foo: ↓[Int]? = nil +} +``` + +```swift +struct Foo { + let foo: ↓[String: Int]? = nil +} +``` + +```swift +struct Foo { + let foo: ↓Set? = nil +} +``` + +```swift +class Foo { + var foo: ↓[Int]? { return nil } +} +``` + +```swift +class Foo { + let foo: ↓[Int]? { return nil }() +} +``` + +```swift +class Foo { + var foo: ↓Set? { return nil } +} +``` + +```swift +class Foo { + let foo: ↓Set? { return nil }() +} +``` + +```swift +struct Foo { + var foo: ↓[Int]? { return nil } +} +``` + +```swift +struct Foo { + let foo: ↓[Int]? { return nil }() +} +``` + +```swift +struct Foo { + var foo: ↓Set? { return nil } +} +``` + +```swift +struct Foo { + let foo: ↓Set? { return nil }() +} +``` + +```swift +enum Foo { + var foo: ↓[Int]? { return nil } +} +``` + +```swift +enum Foo { + let foo: ↓[Int]? { return nil }() +} +``` + +```swift +enum Foo { + var foo: ↓Set? { return nil } +} +``` + +```swift +enum Foo { + let foo: ↓Set? { return nil }() +} +``` + +```swift +class Foo { + func foo() -> [T]? {} +} +``` + +```swift +class Foo { + func foo() -> ↓[String: String]? {} +} +``` + +```swift +class Foo { + func foo() -> [String: [String: String]]? {} +} +``` + +```swift +class Foo { + func foo() -> [String: ↓[String: String]?] {} +} +``` + +```swift +class Foo { + func foo() -> Set? {} +} +``` + +```swift +class Foo { + static func foo() -> [T]? {} +} +``` + +```swift +class Foo { + static func foo() -> ↓[String: String]? {} +} +``` + +```swift +class Foo { + static func foo() -> [String: [String: String]]? {} +} +``` + +```swift +class Foo { + static func foo() -> [String: ↓[String: String]?] {} +} +``` + +```swift +class Foo { + static func foo() -> Set? {} +} +``` + +```swift +class Foo { + func foo() -> ([Int]?) -> String {} +} +``` + +```swift +class Foo { + func foo() -> ([Int]) -> [String]? {} +} +``` + +```swift +struct Foo { + func foo() -> [T]? {} +} +``` + +```swift +struct Foo { + func foo() -> ↓[String: String]? {} +} +``` + +```swift +struct Foo { + func foo() -> [String: [String: String]]? {} +} +``` + +```swift +struct Foo { + func foo() -> [String: ↓[String: String]?] {} +} +``` + +```swift +struct Foo { + func foo() -> Set? {} +} +``` + +```swift +struct Foo { + static func foo() -> [T]? {} +} +``` + +```swift +struct Foo { + static func foo() -> ↓[String: String]? {} +} +``` + +```swift +struct Foo { + static func foo() -> [String: [String: String]]? {} +} +``` + +```swift +struct Foo { + static func foo() -> [String: ↓[String: String]?] {} +} +``` + +```swift +struct Foo { + static func foo() -> Set? {} +} +``` + +```swift +struct Foo { + func foo() -> ([Int]?) -> String {} +} +``` + +```swift +struct Foo { + func foo() -> ([Int]) -> [String]? {} +} +``` + +```swift +enum Foo { + func foo() -> [T]? {} +} +``` + +```swift +enum Foo { + func foo() -> ↓[String: String]? {} +} +``` + +```swift +enum Foo { + func foo() -> [String: [String: String]]? {} +} +``` + +```swift +enum Foo { + func foo() -> [String: ↓[String: String]?] {} +} +``` + +```swift +enum Foo { + func foo() -> Set? {} +} +``` + +```swift +enum Foo { + static func foo() -> [T]? {} +} +``` + +```swift +enum Foo { + static func foo() -> ↓[String: String]? {} +} +``` + +```swift +enum Foo { + static func foo() -> [String: [String: String]]? {} +} +``` + +```swift +enum Foo { + static func foo() -> [String: ↓[String: String]?] {} +} +``` + +```swift +enum Foo { + static func foo() -> Set? {} +} +``` + +```swift +enum Foo { + func foo() -> ([Int]?) -> String {} +} +``` + +```swift +enum Foo { + func foo() -> ([Int]) -> [String]? {} +} +``` + +```swift +class Foo { + func foo(input: ↓[String: String]?) {} +} +``` + +```swift +class Foo { + func foo(input: ↓[String: [String: String]]?) {} +} +``` + +```swift +class Foo { + func foo(input: [String: ↓[String: String]?]) {} +} +``` + +```swift +class Foo { + func foo(input: ↓[String: ↓[String: String]?]?) {} +} +``` + +```swift +class Foo { + func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +class Foo { + func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +class Foo { + static func foo(input: ↓[String: String]?) {} +} +``` + +```swift +class Foo { + static func foo(input: ↓[String: [String: String]]?) {} +} +``` + +```swift +class Foo { + static func foo(input: [String: ↓[String: String]?]) {} +} +``` + +```swift +class Foo { + static func foo(input: ↓[String: ↓[String: String]?]?) {} +} +``` + +```swift +class Foo { + static func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +class Foo { + static func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +struct Foo { + func foo(input: ↓[String: String]?) {} +} +``` + +```swift +struct Foo { + func foo(input: ↓[String: [String: String]]?) {} +} +``` + +```swift +struct Foo { + func foo(input: [String: ↓[String: String]?]) {} +} +``` + +```swift +struct Foo { + func foo(input: ↓[String: ↓[String: String]?]?) {} +} +``` + +```swift +struct Foo { + func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +struct Foo { + func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +struct Foo { + static func foo(input: ↓[String: String]?) {} +} +``` + +```swift +struct Foo { + static func foo(input: ↓[String: [String: String]]?) {} +} +``` + +```swift +struct Foo { + static func foo(input: [String: ↓[String: String]?]) {} +} +``` + +```swift +struct Foo { + static func foo(input: ↓[String: ↓[String: String]?]?) {} +} +``` + +```swift +struct Foo { + static func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +struct Foo { + static func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +enum Foo { + func foo(input: ↓[String: String]?) {} +} +``` + +```swift +enum Foo { + func foo(input: ↓[String: [String: String]]?) {} +} +``` + +```swift +enum Foo { + func foo(input: [String: ↓[String: String]?]) {} +} +``` + +```swift +enum Foo { + func foo(input: ↓[String: ↓[String: String]?]?) {} +} +``` + +```swift +enum Foo { + func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +enum Foo { + func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +enum Foo { + static func foo(input: ↓[String: String]?) {} +} +``` + +```swift +enum Foo { + static func foo(input: ↓[String: [String: String]]?) {} +} +``` + +```swift +enum Foo { + static func foo(input: [String: ↓[String: String]?]) {} +} +``` + +```swift +enum Foo { + static func foo(input: ↓[String: ↓[String: String]?]?) {} +} +``` + +```swift +enum Foo { + static func foo(_ dict1: [K: V], _ dict2: ↓[K: V]?) -> [K: V] +} +``` + +```swift +enum Foo { + static func foo(dict1: [K: V], dict2: ↓[K: V]?) -> [K: V] +} +``` \ No newline at end of file diff --git a/docs/description/duplicate_conditions.md b/docs/description/duplicate_conditions.md new file mode 100644 index 0000000..ef7b800 --- /dev/null +++ b/docs/description/duplicate_conditions.md @@ -0,0 +1,190 @@ +# Duplicate Conditions + +Duplicate sets of conditions in the same branch instruction should be avoided + +* **Identifier:** `duplicate_conditions` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +if x < 5 { + foo() +} else if y == "s" { + bar() +} +``` + +```swift +if x < 5 { + foo() +} +if x < 5 { + bar() +} +``` + +```swift +if x < 5, y == "s" { + foo() +} else if x < 5 { + bar() +} +``` + +```swift +switch x { +case "a": + foo() + bar() +} +``` + +```swift +switch x { +case "a" where y == "s": + foo() +case "a" where y == "t": + bar() +} +``` + +```swift +if let x = maybeAbc { + foo() +} else if let x = maybePqr { + bar() +} +``` + +```swift +if let x = maybeAbc, let z = x.maybeY { + foo() +} else if let x = maybePqr, let z = x.maybeY { + bar() +} +``` + +```swift +if case .p = x { + foo() +} else if case .q = x { + bar() +} +``` + +```swift +if true { + if true { foo() } +} +``` + +## Triggering Examples + +```swift +if ↓x < 5 { + foo() +} else if y == "s" { + bar() +} else if ↓x < 5 { + baz() +} +``` + +```swift +if z { + if ↓x < 5 { + foo() + } else if y == "s" { + bar() + } else if ↓x < 5 { + baz() + } +} +``` + +```swift +if ↓x < 5, y == "s" { + foo() +} else if x < 10 { + bar() +} else if ↓y == "s", x < 5 { + baz() +} +``` + +```swift +switch x { +case ↓"a", "b": + foo() +case "c", ↓"a": + bar() +} +``` + +```swift +switch x { +case ↓"a" where y == "s": + foo() +case ↓"a" where y == "s": + bar() +} +``` + +```swift +if ↓let xyz = maybeXyz { + foo() +} else if ↓let xyz = maybeXyz { + bar() +} +``` + +```swift +if ↓let x = maybeAbc, let z = x.maybeY { + foo() +} else if ↓let x = maybeAbc, let z = x.maybeY { + bar() +} +``` + +```swift +if ↓#available(macOS 10.15, *) { + foo() +} else if ↓#available(macOS 10.15, *) { + bar() +} +``` + +```swift +if ↓case .p = x { + foo() +} else if ↓case .p = x { + bar() +} +``` + +```swift +if ↓x < 5 {} +else if ↓x < 5 {} +else if ↓x < 5 {} +``` \ No newline at end of file diff --git a/docs/description/duplicate_enum_cases.md b/docs/description/duplicate_enum_cases.md new file mode 100644 index 0000000..9e4e80d --- /dev/null +++ b/docs/description/duplicate_enum_cases.md @@ -0,0 +1,76 @@ +# Duplicate Enum Cases + +Enum shouldn't contain multiple cases with the same name + +* **Identifier:** `duplicate_enum_cases` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +enum PictureImport { + case addImage(image: UIImage) + case addData(data: Data) +} +``` + +```swift +enum A { + case add(image: UIImage) +} +enum B { + case add(image: UIImage) +} +``` + +```swift +enum Tag: String { +#if CONFIG_A + case value = "CONFIG_A" +#elseif CONFIG_B + case value = "CONFIG_B" +#else + case value = "CONFIG_DEFAULT" +#endif +} +``` + +```swift +enum Target { +#if os(iOS) + case file +#else + case file(URL) +#endif +} +``` + +## Triggering Examples + +```swift +enum PictureImport { + case ↓add(image: UIImage) + case addURL(url: URL) + case ↓add(data: Data) +} +``` \ No newline at end of file diff --git a/docs/description/duplicate_imports.md b/docs/description/duplicate_imports.md new file mode 100644 index 0000000..a4c1793 --- /dev/null +++ b/docs/description/duplicate_imports.md @@ -0,0 +1,189 @@ +# Duplicate Imports + +Imports should be unique + +* **Identifier:** `duplicate_imports` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +import A +import B +import C +``` + +```swift +import A.B +import A.C +``` + +```swift +@_implementationOnly import A +@_implementationOnly import B +``` + +```swift +@testable import A +@testable import B +``` + +```swift +#if DEBUG + @testable import KsApi +#else + import KsApi +#endif +``` + +```swift +import A // module +import B // module +``` + +```swift +#if TEST +func test() { +} +``` + +```swift +import Foo +@testable import struct Foo.Bar +``` + +## Triggering Examples + +```swift +@_implementationOnly import A +↓@_implementationOnly import A + +``` + +```swift +@testable import A +↓@testable import A + +``` + +```swift +@testable import Foo +import struct Foo.Bar +``` + +```swift +import A +#if DEBUG + @testable import KsApi +#else + import KsApi +#endif +↓import A + +``` + +```swift +import A +↓import class A.Foo + +``` + +```swift +import A +↓import enum A.Foo + +``` + +```swift +import A +↓import func A.Foo + +``` + +```swift +import A +↓import let A.Foo + +``` + +```swift +import A +↓import protocol A.Foo + +``` + +```swift +import A +↓import struct A.Foo + +``` + +```swift +import A +↓import typealias A.Foo + +``` + +```swift +import A +↓import var A.Foo + +``` + +```swift +import A.B +↓import A.B.C + +``` + +```swift +import Foundation +import Dispatch +↓import Foundation + +``` + +```swift +import Foundation +↓import Foundation +↓import Foundation + +``` + +```swift +import Foundation +↓import Foundation.NSString + +``` + +```swift +↓import A.B.C +import A.B + +``` + +```swift +↓import Foundation.NSString +import Foundation + +``` \ No newline at end of file diff --git a/docs/description/duplicated_key_in_dictionary_literal.md b/docs/description/duplicated_key_in_dictionary_literal.md new file mode 100644 index 0000000..1c63b05 --- /dev/null +++ b/docs/description/duplicated_key_in_dictionary_literal.md @@ -0,0 +1,102 @@ +# Duplicated Key in Dictionary Literal + +Dictionary literals with duplicated keys will crash at runtime + +* **Identifier:** `duplicated_key_in_dictionary_literal` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[ + 1: "1", + 2: "2" +] +``` + +```swift +[ + "1": 1, + "2": 2 +] +``` + +```swift +[ + foo: "1", + bar: "2" +] +``` + +```swift +[ + UUID(): "1", + UUID(): "2" +] +``` + +```swift +[ + #line: "1", + #line: "2" +] +``` + +## Triggering Examples + +```swift +[ + 1: "1", + 2: "2", + ↓1: "one" +] +``` + +```swift +[ + "1": 1, + "2": 2, + ↓"2": 2 +] +``` + +```swift +[ + foo: "1", + bar: "2", + baz: "3", + ↓foo: "4", + zaz: "5" +] +``` + +```swift +[ + .one: "1", + .two: "2", + .three: "3", + ↓.one: "1", + .four: "4", + .five: "5" +] +``` \ No newline at end of file diff --git a/docs/description/dynamic_inline.md b/docs/description/dynamic_inline.md new file mode 100644 index 0000000..ac73a89 --- /dev/null +++ b/docs/description/dynamic_inline.md @@ -0,0 +1,78 @@ +# Dynamic Inline + +Avoid using 'dynamic' and '@inline(__always)' together + +* **Identifier:** `dynamic_inline` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +class C { +dynamic func f() {}} +``` + +```swift +class C { +@inline(__always) func f() {}} +``` + +```swift +class C { +@inline(never) dynamic func f() {}} +``` + +## Triggering Examples + +```swift +class C { +@inline(__always) dynamic ↓func f() {} +} +``` + +```swift +class C { +@inline(__always) public dynamic ↓func f() {} +} +``` + +```swift +class C { +@inline(__always) dynamic internal ↓func f() {} +} +``` + +```swift +class C { +@inline(__always) +dynamic ↓func f() {} +} +``` + +```swift +class C { +@inline(__always) +dynamic +↓func f() {} +} +``` \ No newline at end of file diff --git a/docs/description/empty_collection_literal.md b/docs/description/empty_collection_literal.md new file mode 100644 index 0000000..9670d22 --- /dev/null +++ b/docs/description/empty_collection_literal.md @@ -0,0 +1,78 @@ +# Empty Collection Literal + +Prefer checking `isEmpty` over comparing collection to an empty array or dictionary literal + +* **Identifier:** `empty_collection_literal` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +myArray = [] +``` + +```swift +myArray.isEmpty +``` + +```swift +!myArray.isEmpty +``` + +```swift +myDict = [:] +``` + +## Triggering Examples + +```swift +myArray↓ == [] +``` + +```swift +myArray↓ != [] +``` + +```swift +myArray↓ == [ ] +``` + +```swift +myDict↓ == [:] +``` + +```swift +myDict↓ != [:] +``` + +```swift +myDict↓ == [: ] +``` + +```swift +myDict↓ == [ :] +``` + +```swift +myDict↓ == [ : ] +``` \ No newline at end of file diff --git a/docs/description/empty_count.md b/docs/description/empty_count.md new file mode 100644 index 0000000..8741b78 --- /dev/null +++ b/docs/description/empty_count.md @@ -0,0 +1,122 @@ +# Empty Count + +Prefer checking `isEmpty` over comparing `count` to zero + +* **Identifier:** `empty_count` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + error +
+ only_after_dot + + false +
+ +## Non Triggering Examples + +```swift +var count = 0 +``` + +```swift +[Int]().isEmpty +``` + +```swift +[Int]().count > 1 +``` + +```swift +[Int]().count == 1 +``` + +```swift +[Int]().count == 0xff +``` + +```swift +[Int]().count == 0b01 +``` + +```swift +[Int]().count == 0o07 +``` + +```swift +discount == 0 +``` + +```swift +order.discount == 0 +``` + +```swift +let rule = #Rule(Tips.Event(id: "someTips")) { $0.donations.count == 0 } +``` + +## Triggering Examples + +```swift +[Int]().↓count == 0 +``` + +```swift +0 == [Int]().↓count +``` + +```swift +[Int]().↓count==0 +``` + +```swift +[Int]().↓count > 0 +``` + +```swift +[Int]().↓count != 0 +``` + +```swift +[Int]().↓count == 0x0 +``` + +```swift +[Int]().↓count == 0x00_00 +``` + +```swift +[Int]().↓count == 0b00 +``` + +```swift +[Int]().↓count == 0o00 +``` + +```swift +↓count == 0 +``` + +```swift +#ExampleMacro { $0.list.↓count == 0 } +``` \ No newline at end of file diff --git a/docs/description/empty_enum_arguments.md b/docs/description/empty_enum_arguments.md new file mode 100644 index 0000000..f45d978 --- /dev/null +++ b/docs/description/empty_enum_arguments.md @@ -0,0 +1,203 @@ +# Empty Enum Arguments + +Arguments can be omitted when matching enums with associated values if they are not used + +* **Identifier:** `empty_enum_arguments` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +switch foo { +case .bar: break +} +``` + +```swift +switch foo { +case .bar(let x): break +} +``` + +```swift +switch foo { +case let .bar(x): break +} +``` + +```swift +switch (foo, bar) { +case (_, _): break +} +``` + +```swift +switch foo { +case "bar".uppercased(): break +} +``` + +```swift +switch (foo, bar) { +case (_, _) where !something: break +} +``` + +```swift +switch foo { +case (let f as () -> String)?: break +} +``` + +```swift +switch foo { +case .bar(Baz()): break +} +``` + +```swift +switch foo { +case .bar(.init()): break +} +``` + +```swift +switch foo { +default: break +} +``` + +```swift +if case .bar = foo { +} +``` + +```swift +guard case .bar = foo else { +} +``` + +```swift +if foo == .bar() {} +``` + +```swift +guard foo == .bar() else { return } +``` + +```swift +if case .appStore = self.appInstaller, !UIDevice.isSimulator() { + viewController.present(self, animated: false) +} else { + UIApplication.shared.open(self.appInstaller.url) +} +``` + +```swift +let updatedUserNotificationSettings = deepLink.filter { nav in + guard case .settings(.notifications(_, nil)) = nav else { return false } + return true +} +``` + +## Triggering Examples + +```swift +switch foo { +case .bar↓(_): break +} +``` + +```swift +switch foo { +case .bar↓(): break +} +``` + +```swift +switch foo { +case .bar↓(_), .bar2↓(_): break +} +``` + +```swift +switch foo { +case .bar↓() where method() > 2: break +} +``` + +```swift +switch foo { +case .bar(.baz↓()): break +} +``` + +```swift +switch foo { +case .bar(.baz↓(_)): break +} +``` + +```swift +func example(foo: Foo) { + switch foo { + case .bar↓(_): + break + } +} +``` + +```swift +if case .bar↓(_) = foo { +} +``` + +```swift +guard case .bar↓(_) = foo else { +} +``` + +```swift +if case .bar↓() = foo { +} +``` + +```swift +guard case .bar↓() = foo else { +} +``` + +```swift +if case .appStore↓(_) = self.appInstaller, !UIDevice.isSimulator() { + viewController.present(self, animated: false) +} else { + UIApplication.shared.open(self.appInstaller.url) +} +``` + +```swift +let updatedUserNotificationSettings = deepLink.filter { nav in + guard case .settings(.notifications↓(_, _)) = nav else { return false } + return true +} +``` \ No newline at end of file diff --git a/docs/description/empty_parameters.md b/docs/description/empty_parameters.md new file mode 100644 index 0000000..e2d24d1 --- /dev/null +++ b/docs/description/empty_parameters.md @@ -0,0 +1,70 @@ +# Empty Parameters + +Prefer `() -> ` over `Void -> ` + +* **Identifier:** `empty_parameters` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let abc: () -> Void = {} +``` + +```swift +func foo(completion: () -> Void) +``` + +```swift +func foo(completion: () throws -> Void) +``` + +```swift +let foo: (ConfigurationTests) -> Void throws -> Void) +``` + +```swift +let foo: (ConfigurationTests) -> Void throws -> Void) +``` + +```swift +let foo: (ConfigurationTests) ->Void throws -> Void) +``` + +## Triggering Examples + +```swift +let abc: ↓(Void) -> Void = {} +``` + +```swift +func foo(completion: ↓(Void) -> Void) +``` + +```swift +func foo(completion: ↓(Void) throws -> Void) +``` + +```swift +let foo: ↓(Void) -> () throws -> Void) +``` \ No newline at end of file diff --git a/docs/description/empty_parentheses_with_trailing_closure.md b/docs/description/empty_parentheses_with_trailing_closure.md new file mode 100644 index 0000000..1855809 --- /dev/null +++ b/docs/description/empty_parentheses_with_trailing_closure.md @@ -0,0 +1,86 @@ +# Empty Parentheses with Trailing Closure + +When using trailing closures, empty parentheses should be avoided after the method call + +* **Identifier:** `empty_parentheses_with_trailing_closure` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[1, 2].map { $0 + 1 } +``` + +```swift +[1, 2].map({ $0 + 1 }) +``` + +```swift +[1, 2].reduce(0) { $0 + $1 } +``` + +```swift +[1, 2].map { number in + number + 1 +} +``` + +```swift +let isEmpty = [1, 2].isEmpty() +``` + +```swift +UIView.animateWithDuration(0.3, animations: { + self.disableInteractionRightView.alpha = 0 +}, completion: { _ in + () +}) +``` + +## Triggering Examples + +```swift +[1, 2].map↓() { $0 + 1 } +``` + +```swift +[1, 2].map↓( ) { $0 + 1 } +``` + +```swift +[1, 2].map↓() { number in + number + 1 +} +``` + +```swift +[1, 2].map↓( ) { number in + number + 1 +} +``` + +```swift +func foo() -> [Int] { + return [1, 2].map↓() { $0 + 1 } +} +``` \ No newline at end of file diff --git a/docs/description/empty_string.md b/docs/description/empty_string.md new file mode 100644 index 0000000..794d4cd --- /dev/null +++ b/docs/description/empty_string.md @@ -0,0 +1,64 @@ +# Empty String + +Prefer checking `isEmpty` over comparing `string` to an empty string literal + +* **Identifier:** `empty_string` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +myString.isEmpty +``` + +```swift +!myString.isEmpty +``` + +```swift +""" +foo== +""" +``` + +## Triggering Examples + +```swift +myString↓ == "" +``` + +```swift +myString↓ != "" +``` + +```swift +myString↓=="" +``` + +```swift +myString↓ == #""# +``` + +```swift +myString↓ == ##""## +``` \ No newline at end of file diff --git a/docs/description/empty_xctest_method.md b/docs/description/empty_xctest_method.md new file mode 100644 index 0000000..6eb3aa9 --- /dev/null +++ b/docs/description/empty_xctest_method.md @@ -0,0 +1,195 @@ +# Empty XCTest Method + +Empty XCTest method should be avoided + +* **Identifier:** `empty_xctest_method` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ test_parent_classes + + ["QuickSpec", "XCTestCase"] +
+ +## Non Triggering Examples + +```swift +class TotoTests: XCTestCase { + var foobar: Foobar? + + override func setUp() { + super.setUp() + foobar = Foobar() + } + + override func setUpWithError() throws { + foobar = nil + } + + override func tearDown() { + foobar = nil + super.tearDown() + } + + func testFoo() { + XCTAssertTrue(foobar?.foo) + } + + func testBar() { + // comment... + + XCTAssertFalse(foobar?.bar) + + // comment... + } + + func testBaz() { + _ = 4 + 4 + } +} +``` + +```swift +class Foobar { + func setUp() {} + + func tearDown() {} + + func testFoo() {} +} +``` + +```swift +class TotoTests: XCTestCase { + func setUp(with object: Foobar) {} + + func tearDown(object: Foobar) {} + + func testFoo(_ foo: Foobar) {} + + func testBar(bar: (String) -> Int) {} +} +``` + +```swift +class TotoTests: XCTestCase { + func testFoo() { XCTAssertTrue(foobar?.foo) } + + func testBar() { XCTAssertFalse(foobar?.bar) } +} +``` + +```swift +class TotoTests: XCTestCase { + override class var runsForEachTargetApplicationUIConfiguration: Bool { true } + + static var allTests = [("testFoo", testFoo)] + + func testFoo() { XCTAssert(true) } +} +``` + +## Triggering Examples + +```swift +class TotoTests: XCTestCase { + override ↓func setUp() { + } + + override ↓func tearDown() { + + } + + ↓func testFoo() { + + + } + + ↓func testBar() { + + + + } + + func helperFunction() { + } +} +``` + +```swift +class TotoTests: XCTestCase { + override ↓func setUp() {} + + override ↓func tearDown() {} + + ↓func testFoo() {} + + func helperFunction() {} +} +``` + +```swift +class TotoTests: XCTestCase { + override ↓func setUp() { + // comment... + } + + override ↓func tearDown() { + // comment... + // comment... + } + + ↓func testFoo() { + // comment... + + // comment... + + // comment... + } + + ↓func testBar() { + /* + * comment... + * + * comment... + * + * comment... + */ + } + + func helperFunction() { + } +} +``` + +```swift +class FooTests: XCTestCase { + override ↓func setUp() {} +} + +class BarTests: XCTestCase { + ↓func testFoo() {} +} +``` \ No newline at end of file diff --git a/docs/description/enum_case_associated_values_count.md b/docs/description/enum_case_associated_values_count.md new file mode 100644 index 0000000..bc1869b --- /dev/null +++ b/docs/description/enum_case_associated_values_count.md @@ -0,0 +1,64 @@ +# Enum Case Associated Values Count + +The number of associated values in an enum case should be low. + +* **Identifier:** `enum_case_associated_values_count` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ warning + + 5 +
+ error + + 6 +
+ +## Non Triggering Examples + +```swift +enum Employee { + case fullTime(name: String, retirement: Date, designation: String, contactNumber: Int) + case partTime(name: String, age: Int, contractEndDate: Date) +} +``` + +```swift +enum Barcode { + case upc(Int, Int, Int, Int) +} +``` + +## Triggering Examples + +```swift +enum Employee { + case ↓fullTime(name: String, retirement: Date, age: Int, designation: String, contactNumber: Int) + case ↓partTime(name: String, contractEndDate: Date, age: Int, designation: String, contactNumber: Int) +} +``` + +```swift +enum Barcode { + case ↓upc(Int, Int, Int, Int, Int, Int) +} +``` \ No newline at end of file diff --git a/docs/description/expiring_todo.md b/docs/description/expiring_todo.md new file mode 100644 index 0000000..672bc7c --- /dev/null +++ b/docs/description/expiring_todo.md @@ -0,0 +1,156 @@ +# Expiring Todo + +TODOs and FIXMEs should be resolved prior to their expiry date. + +* **Identifier:** `expiring_todo` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ approaching_expiry_severity + + warning +
+ expired_severity + + error +
+ bad_formatting_severity + + error +
+ approaching_expiry_threshold + + 15 +
+ date_delimiters + + + + + + + + + + + + + + + +
KeyValue
+ opening + + "[" +
+ closing + + "]" +
+
+ date_format + + "MM/dd/yyyy" +
+ date_separator + + "/" +
+ +## Non Triggering Examples + +```swift +// notaTODO: +``` + +```swift +// notaFIXME: +``` + +```swift +// TODO: [12/31/9999] +``` + +```swift +// TODO(note) +``` + +```swift +// FIXME(note) +``` + +```swift +/* FIXME: */ +``` + +```swift +/* TODO: */ +``` + +```swift +/** FIXME: */ +``` + +```swift +/** TODO: */ +``` + +## Triggering Examples + +```swift +// TODO: [↓10/14/2019] +``` + +```swift +// FIXME: [↓10/14/2019] +``` + +```swift +// FIXME: [↓1/14/2019] +``` + +```swift +// FIXME: [↓10/14/2019] +``` + +```swift +// TODO: [↓9999/14/10] +``` \ No newline at end of file diff --git a/docs/description/explicit_acl.md b/docs/description/explicit_acl.md new file mode 100644 index 0000000..ded1ba2 --- /dev/null +++ b/docs/description/explicit_acl.md @@ -0,0 +1,193 @@ +# Explicit ACL + +All declarations should specify Access Control Level keywords explicitly + +* **Identifier:** `explicit_acl` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +internal enum A {} +``` + +```swift +public final class B {} +``` + +```swift +private struct C {} +``` + +```swift +internal enum A { internal enum B {} } +``` + +```swift +internal final class Foo {} +``` + +```swift +internal +class Foo { + private let bar = 5 +} +``` + +```swift +internal func a() { let a = } +``` + +```swift +private func a() { func innerFunction() { } } +``` + +```swift +private enum Foo { enum Bar { } } +``` + +```swift +private struct C { let d = 5 } +``` + +```swift +internal protocol A { + func b() +} +``` + +```swift +internal protocol A { + var b: Int +} +``` + +```swift +internal class A { deinit {} } +``` + +```swift +extension A: Equatable {} +``` + +```swift +extension A {} +``` + +```swift +extension Foo { + internal func bar() {} +} +``` + +```swift +internal enum Foo { + case bar +} +``` + +```swift +extension Foo { + public var isValid: Bool { + let result = true + return result + } +} +``` + +```swift +extension Foo { + private var isValid: Bool { + get { + return true + } + set(newValue) { + print(newValue) + } + } +} +``` + +```swift +private extension Foo { + var isValid: Bool { true } + struct S { + let b = 2 + } +} +``` + +## Triggering Examples + +```swift +↓enum A {} +``` + +```swift +final ↓class B {} +``` + +```swift +internal struct C { ↓let d = 5 } +``` + +```swift +public struct C { private(set) ↓var d = 5 } +``` + +```swift +internal struct C { static ↓let d = 5 } +``` + +```swift +public struct C { ↓let d = 5 } +``` + +```swift +public struct C { ↓init() } +``` + +```swift +static ↓func a() {} +``` + +```swift +internal let a = 0 +↓func b() {} +``` + +```swift +extension Foo { + ↓func bar() {} + static ↓func baz() {} +} +``` + +```swift +public extension E { + let a = 1 + struct S { + ↓let b = 2 + } +} +``` \ No newline at end of file diff --git a/docs/description/explicit_enum_raw_value.md b/docs/description/explicit_enum_raw_value.md new file mode 100644 index 0000000..b11b3b1 --- /dev/null +++ b/docs/description/explicit_enum_raw_value.md @@ -0,0 +1,104 @@ +# Explicit Enum Raw Value + +Enums should be explicitly assigned their raw values + +* **Identifier:** `explicit_enum_raw_value` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +enum Numbers { + case int(Int) + case short(Int16) +} +``` + +```swift +enum Numbers: Int { + case one = 1 + case two = 2 +} +``` + +```swift +enum Numbers: Double { + case one = 1.1 + case two = 2.2 +} +``` + +```swift +enum Numbers: String { + case one = "one" + case two = "two" +} +``` + +```swift +protocol Algebra {} +enum Numbers: Algebra { + case one +} +``` + +## Triggering Examples + +```swift +enum Numbers: Int { + case one = 10, ↓two, three = 30 +} +``` + +```swift +enum Numbers: NSInteger { + case ↓one +} +``` + +```swift +enum Numbers: String { + case ↓one + case ↓two +} +``` + +```swift +enum Numbers: String { + case ↓one, two = "two" +} +``` + +```swift +enum Numbers: Decimal { + case ↓one, ↓two +} +``` + +```swift +enum Outer { + enum Numbers: Decimal { + case ↓one, ↓two + } +} +``` \ No newline at end of file diff --git a/docs/description/explicit_init.md b/docs/description/explicit_init.md new file mode 100644 index 0000000..3b5a317 --- /dev/null +++ b/docs/description/explicit_init.md @@ -0,0 +1,116 @@ +# Explicit Init + +Explicitly calling .init() should be avoided + +* **Identifier:** `explicit_init` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ include_bare_init + + false +
+ +## Non Triggering Examples + +```swift +import Foundation +class C: NSObject { + override init() { + super.init() + } +} +``` + +```swift +struct S { + let n: Int +} +extension S { + init() { + self.init(n: 1) + } +} +``` + +```swift +[1].flatMap(String.init) +``` + +```swift +[String.self].map { $0.init(1) } +``` + +```swift +[String.self].map { type in type.init(1) } +``` + +```swift +Observable.zip(obs1, obs2, resultSelector: MyType.init).asMaybe() +``` + +```swift +_ = GleanMetrics.Tabs.someType.init() +``` + +```swift +Observable.zip( + obs1, + obs2, + resultSelector: MyType.init +).asMaybe() +``` + +## Triggering Examples + +```swift +[1].flatMap{String↓.init($0)} +``` + +```swift +[String.self].map { Type in Type↓.init(1) } +``` + +```swift +func foo() -> [String] { + return [1].flatMap { String↓.init($0) } +} +``` + +```swift +_ = GleanMetrics.Tabs.GroupedTabExtra↓.init() +``` + +```swift +_ = Set↓.init() +``` + +```swift +Observable.zip( + obs1, + obs2, + resultSelector: { MyType↓.init($0, $1) } +).asMaybe() +``` \ No newline at end of file diff --git a/docs/description/explicit_self.md b/docs/description/explicit_self.md new file mode 100644 index 0000000..52fb43a --- /dev/null +++ b/docs/description/explicit_self.md @@ -0,0 +1,115 @@ +# Explicit Self + +Instance variables and functions should be explicitly accessed with 'self.' + +* **Identifier:** `explicit_self` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** Yes +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +struct A { + func f1() {} + func f2() { + self.f1() + } +} +``` + +```swift +struct A { + let p1: Int + func f1() { + _ = self.p1 + } +} +``` + +```swift +@propertyWrapper +struct Wrapper { + let wrappedValue: Value + var projectedValue: [Value] { + [self.wrappedValue] + } +} +struct A { + @Wrapper var p1: Int + func f1() { + self.$p1 + self._p1 + } +} +func f1() { + A(p1: 10).$p1 +} +``` + +## Triggering Examples + +```swift +struct A { + func f1() {} + func f2() { + ↓f1() + } +} +``` + +```swift +struct A { + let p1: Int + func f1() { + _ = ↓p1 + } +} +``` + +```swift +struct A { + func f1(a b: Int) {} + func f2() { + ↓f1(a: 0) + } +} +``` + +```swift +@propertyWrapper +struct Wrapper { + let wrappedValue: Value + var projectedValue: [Value] { + [self.wrappedValue] + } +} +struct A { + @Wrapper var p1: Int + func f1() { + ↓$p1 + ↓_p1 + } +} +func f1() { + A(p1: 10).$p1 +} +``` \ No newline at end of file diff --git a/docs/description/explicit_top_level_acl.md b/docs/description/explicit_top_level_acl.md new file mode 100644 index 0000000..3fa31d6 --- /dev/null +++ b/docs/description/explicit_top_level_acl.md @@ -0,0 +1,89 @@ +# Explicit Top Level ACL + +Top-level declarations should specify Access Control Level keywords explicitly + +* **Identifier:** `explicit_top_level_acl` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +internal enum A {} +``` + +```swift +public final class B {} +``` + +```swift +private struct S1 { + struct S2 {} +} +``` + +```swift +internal enum A { enum B {} } +``` + +```swift +internal final actor Foo {} +``` + +```swift +internal typealias Foo = Bar +``` + +```swift +internal func a() {} +``` + +```swift +extension A: Equatable {} +``` + +```swift +extension A {} +``` + +## Triggering Examples + +```swift +↓enum A {} +``` + +```swift +final ↓class B {} +``` + +```swift +↓protocol P {} +``` + +```swift +↓func a() {} +``` + +```swift +internal let a = 0 +↓func b() {} +``` \ No newline at end of file diff --git a/docs/description/explicit_type_interface.md b/docs/description/explicit_type_interface.md new file mode 100644 index 0000000..e7cce3f --- /dev/null +++ b/docs/description/explicit_type_interface.md @@ -0,0 +1,106 @@ +# Explicit Type Interface + +Properties should have a type interface + +* **Identifier:** `explicit_type_interface` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ excluded + + [] +
+ allow_redundancy + + false +
+ +## Non Triggering Examples + +```swift +class Foo { + var myVar: Int? = 0 +} +``` + +```swift +class Foo { + let myVar: Int? = 0, s: String = "" +} +``` + +```swift +class Foo { + static var myVar: Int? = 0 +} +``` + +```swift +class Foo { + class var myVar: Int? = 0 +} +``` + +## Triggering Examples + +```swift +class Foo { + var ↓myVar = 0 +} +``` + +```swift +class Foo { + let ↓mylet = 0 +} +``` + +```swift +class Foo { + static var ↓myStaticVar = 0 +} +``` + +```swift +class Foo { + class var ↓myClassVar = 0 +} +``` + +```swift +class Foo { + let ↓myVar = Int(0), ↓s = "" +} +``` + +```swift +class Foo { + let ↓myVar = Set(0) +} +``` \ No newline at end of file diff --git a/docs/description/extension_access_modifier.md b/docs/description/extension_access_modifier.md new file mode 100644 index 0000000..8852a23 --- /dev/null +++ b/docs/description/extension_access_modifier.md @@ -0,0 +1,207 @@ +# Extension Access Modifier + +Prefer to use extension access modifiers + +* **Identifier:** `extension_access_modifier` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +extension Foo: SomeProtocol { + public var bar: Int { return 1 } +} +``` + +```swift +extension Foo { + private var bar: Int { return 1 } + public var baz: Int { return 1 } +} +``` + +```swift +extension Foo { + private var bar: Int { return 1 } + public func baz() {} +} +``` + +```swift +extension Foo { + var bar: Int { return 1 } + var baz: Int { return 1 } +} +``` + +```swift +extension Foo { + var bar: Int { return 1 } + internal var baz: Int { return 1 } +} +``` + +```swift +internal extension Foo { + var bar: Int { return 1 } + var baz: Int { return 1 } +} +``` + +```swift +public extension Foo { + var bar: Int { return 1 } + var baz: Int { return 1 } +} +``` + +```swift +public extension Foo { + var bar: Int { return 1 } + internal var baz: Int { return 1 } +} +``` + +```swift +extension Foo { + private var bar: Int { return 1 } + private var baz: Int { return 1 } +} +``` + +```swift +extension Foo { + open var bar: Int { return 1 } + open var baz: Int { return 1 } +} +``` + +```swift +extension Foo { + func setup() {} + public func update() {} +} +``` + +```swift +private extension Foo { + private var bar: Int { return 1 } + var baz: Int { return 1 } +} +``` + +```swift +extension Foo { + internal private(set) var bar: Int { + get { Foo.shared.bar } + set { Foo.shared.bar = newValue } + } +} +``` + +```swift +extension Foo { + private(set) internal var bar: Int { + get { Foo.shared.bar } + set { Foo.shared.bar = newValue } + } +} +``` + +```swift +public extension Foo { + private(set) var value: Int { 1 } +} +``` + +## Triggering Examples + +```swift +↓extension Foo { + public var bar: Int { return 1 } + public var baz: Int { return 1 } +} +``` + +```swift +↓extension Foo { + public var bar: Int { return 1 } + public func baz() {} +} +``` + +```swift +public extension Foo { + ↓public func bar() {} + ↓public func baz() {} +} +``` + +```swift +↓extension Foo { + public var bar: Int { + let value = 1 + return value + } + + public var baz: Int { return 1 } +} +``` + +```swift +↓extension Array where Element: Equatable { + public var unique: [Element] { + var uniqueValues = [Element]() + for item in self where !uniqueValues.contains(item) { + uniqueValues.append(item) + } + return uniqueValues + } +} +``` + +```swift +↓extension Foo { + #if DEBUG + public var bar: Int { + let value = 1 + return value + } + #endif + + public var baz: Int { return 1 } +} +``` + +```swift +public extension Foo { + ↓private func bar() {} + ↓private func baz() {} +} +``` + +```swift +↓extension Foo { + private(set) public var value: Int { 1 } +} +``` \ No newline at end of file diff --git a/docs/description/fallthrough.md b/docs/description/fallthrough.md new file mode 100644 index 0000000..c0fead2 --- /dev/null +++ b/docs/description/fallthrough.md @@ -0,0 +1,46 @@ +# Fallthrough + +Fallthrough should be avoided + +* **Identifier:** `fallthrough` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +switch foo { +case .bar, .bar2, .bar3: + something() +} +``` + +## Triggering Examples + +```swift +switch foo { +case .bar: + ↓fallthrough +case .bar2: + something() +} +``` \ No newline at end of file diff --git a/docs/description/fatal_error_message.md b/docs/description/fatal_error_message.md new file mode 100644 index 0000000..79e97a8 --- /dev/null +++ b/docs/description/fatal_error_message.md @@ -0,0 +1,54 @@ +# Fatal Error Message + +A fatalError call should have a message + +* **Identifier:** `fatal_error_message` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func foo() { + fatalError("Foo") +} +``` + +```swift +func foo() { + fatalError(x) +} +``` + +## Triggering Examples + +```swift +func foo() { + ↓fatalError("") +} +``` + +```swift +func foo() { + ↓fatalError() +} +``` \ No newline at end of file diff --git a/docs/description/file_header.md b/docs/description/file_header.md new file mode 100644 index 0000000..e962e96 --- /dev/null +++ b/docs/description/file_header.md @@ -0,0 +1,62 @@ +# File Header + +Header comments should be consistent with project patterns. The SWIFTLINT_CURRENT_FILENAME placeholder can optionally be used in the required and forbidden patterns. It will be replaced by the real file name. + +* **Identifier:** `file_header` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = "Copyright" +``` + +```swift +let foo = 2 // Copyright +``` + +```swift +let foo = 2 + // Copyright +``` + +## Triggering Examples + +```swift +// ↓Copyright +``` + +```swift +// +// ↓Copyright +``` + +```swift +// +// FileHeaderRule.swift +// SwiftLint +// +// Created by Marcelo Fabri on 27/11/16. +// ↓Copyright © 2016 Realm. All rights reserved. +// +``` \ No newline at end of file diff --git a/docs/description/file_length.md b/docs/description/file_length.md new file mode 100644 index 0000000..55e1c22 --- /dev/null +++ b/docs/description/file_length.md @@ -0,0 +1,1665 @@ +# File Length + +Files should not span too many lines. + +* **Identifier:** `file_length` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 400 +
+ error + + 1000 +
+ ignore_comment_only_lines + + false +
+ +## Non Triggering Examples + +```swift +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") + +``` + +## Triggering Examples + +```swift +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") + +``` + +```swift +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +print("swiftlint") +// + +``` + +```swift +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + +print("swiftlint") + + +``` \ No newline at end of file diff --git a/docs/description/file_name.md b/docs/description/file_name.md new file mode 100644 index 0000000..7f05aa8 --- /dev/null +++ b/docs/description/file_name.md @@ -0,0 +1,66 @@ +# File Name + +File name should match a type or extension declared in the file (if any) + +* **Identifier:** `file_name` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ excluded + + ["LinuxMain.swift", "main.swift"] +
+ prefix_pattern + + "" +
+ suffix_pattern + + "\+.*" +
+ nested_type_separator + + "." +
+ require_fully_qualified_names + + false +
\ No newline at end of file diff --git a/docs/description/file_name_no_space.md b/docs/description/file_name_no_space.md new file mode 100644 index 0000000..26eec90 --- /dev/null +++ b/docs/description/file_name_no_space.md @@ -0,0 +1,34 @@ +# File Name no Space + +File name should not contain any whitespace + +* **Identifier:** `file_name_no_space` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ excluded + + [] +
\ No newline at end of file diff --git a/docs/description/file_types_order.md b/docs/description/file_types_order.md new file mode 100644 index 0000000..93fcddf --- /dev/null +++ b/docs/description/file_types_order.md @@ -0,0 +1,261 @@ +# File Types Order + +Specifies how the types within a file should be ordered. + +* **Identifier:** `file_types_order` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ order + + [[supporting_type], [main_type], [extension], [preview_provider], [library_content_provider]] +
+ +## Non Triggering Examples + +```swift +// Supporting Types +protocol TestViewControllerDelegate { + func didPressTrackedButton() +} + +// Main Type +class TestViewController: UIViewController { + // Type Aliases + typealias CompletionHandler = ((TestEnum) -> Void) + + // Subtypes + class TestClass { + // 10 lines + } + + struct TestStruct { + // 3 lines + } + + enum TestEnum { + // 5 lines + } + + // Stored Type Properties + static let cellIdentifier: String = "AmazingCell" + + // Stored Instance Properties + var shouldLayoutView1: Bool! + weak var delegate: TestViewControllerDelegate? + private var hasLayoutedView1: Bool = false + private var hasLayoutedView2: Bool = false + + // Computed Instance Properties + private var hasAnyLayoutedView: Bool { + return hasLayoutedView1 || hasLayoutedView2 + } + + // IBOutlets + @IBOutlet private var view1: UIView! + @IBOutlet private var view2: UIView! + + // Initializers + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // Type Methods + static func makeViewController() -> TestViewController { + // some code + } + + // Life-Cycle Methods + override func viewDidLoad() { + super.viewDidLoad() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + } + + // IBActions + @IBAction func goNextButtonPressed() { + goToNextVc() + delegate?.didPressTrackedButton() + } + + @objc + func goToRandomVcButtonPressed() { + goToRandomVc() + } + + // MARK: Other Methods + func goToNextVc() { /* TODO */ } + + func goToInfoVc() { /* TODO */ } + + func goToRandomVc() { + let viewCtrl = getRandomVc() + present(viewCtrl, animated: true) + } + + private func getRandomVc() -> UIViewController { return UIViewController() } + + // Subscripts + subscript(_ someIndexThatIsNotEvenUsed: Int) -> String { + get { + return "This is just a test" + } + + set { + log.warning("Just a test", newValue) + } + } +} + +// Extensions +extension TestViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } +} +``` + +```swift +// Only extensions +extension Foo {} +extension Bar { +} +``` + +```swift +// Main Type +struct ContentView: View { + var body: some View { + Text("Hello, World!") + } +} + +// Preview Provider +struct ContentView_Previews: PreviewProvider { + static var previews: some View { ContentView() } +} + +// Library Content Provider +struct ContentView_LibraryContent: LibraryContentProvider { + var views: [LibraryItem] { + LibraryItem(ContentView()) + } +} +``` + +## Triggering Examples + +```swift +↓class TestViewController: UIViewController {} + +// Supporting Types +protocol TestViewControllerDelegate { + func didPressTrackedButton() +} +``` + +```swift +// Extensions +↓extension TestViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } +} + +class TestViewController: UIViewController {} +``` + +```swift +// Supporting Types +protocol TestViewControllerDelegate { + func didPressTrackedButton() +} + +↓class TestViewController: UIViewController {} + +// Supporting Types +protocol TestViewControllerDelegate { + func didPressTrackedButton() +} +``` + +```swift +// Supporting Types +protocol TestViewControllerDelegate { + func didPressTrackedButton() +} + +// Extensions +↓extension TestViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } +} + +class TestViewController: UIViewController {} + +// Extensions +extension TestViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } +} +``` + +```swift +// Preview Provider +↓struct ContentView_Previews: PreviewProvider { + static var previews: some View { ContentView() } +} + +// Main Type +struct ContentView: View { + var body: some View { + Text("Hello, World!") + } +} +``` + +```swift +// Library Content Provider +↓struct ContentView_LibraryContent: LibraryContentProvider { + var views: [LibraryItem] { + LibraryItem(ContentView()) + } +} + +// Main Type +struct ContentView: View { + var body: some View { + Text("Hello, World!") + } +} +``` \ No newline at end of file diff --git a/docs/description/final_test_case.md b/docs/description/final_test_case.md new file mode 100644 index 0000000..a44b68b --- /dev/null +++ b/docs/description/final_test_case.md @@ -0,0 +1,80 @@ +# Final Test Case + +Test cases should be final + +* **Identifier:** `final_test_case` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ test_parent_classes + + ["QuickSpec", "XCTestCase"] +
+ +## Non Triggering Examples + +```swift +final class Test: XCTestCase {} +``` + +```swift +open class Test: XCTestCase {} +``` + +```swift +public final class Test: QuickSpec {} +``` + +```swift +class Test: MyTestCase {} +``` + +```swift +// +// test_parent_classes: ["MyTestCase", "QuickSpec", "XCTestCase"] +// + +struct Test: MyTestCase {} + +``` + +## Triggering Examples + +```swift +class ↓Test: XCTestCase {} +``` + +```swift +public class ↓Test: QuickSpec {} +``` + +```swift +// +// test_parent_classes: ["MyTestCase", "QuickSpec", "XCTestCase"] +// + +class ↓Test: MyTestCase {} + +``` \ No newline at end of file diff --git a/docs/description/first_where.md b/docs/description/first_where.md new file mode 100644 index 0000000..e76d1d3 --- /dev/null +++ b/docs/description/first_where.md @@ -0,0 +1,95 @@ +# First Where + +Prefer using `.first(where:)` over `.filter { }.first` in collections + +* **Identifier:** `first_where` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +kinds.filter(excludingKinds.contains).isEmpty && kinds.first == .identifier +``` + +```swift +myList.first(where: { $0 % 2 == 0 }) +``` + +```swift +match(pattern: pattern).filter { $0.first == .identifier } +``` + +```swift +(myList.filter { $0 == 1 }.suffix(2)).first +``` + +```swift +collection.filter("stringCol = '3'").first +``` + +```swift +realm?.objects(User.self).filter(NSPredicate(format: "email ==[c] %@", email)).first +``` + +```swift +if let pause = timeTracker.pauses.filter("beginDate < %@", beginDate).first { print(pause) } +``` + +## Triggering Examples + +```swift +↓myList.filter { $0 % 2 == 0 }.first +``` + +```swift +↓myList.filter({ $0 % 2 == 0 }).first +``` + +```swift +↓myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first +``` + +```swift +↓myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first?.something() +``` + +```swift +↓myList.filter(someFunction).first +``` + +```swift +↓myList.filter({ $0 % 2 == 0 }) +.first +``` + +```swift +(↓myList.filter { $0 == 1 }).first +``` + +```swift +↓myListOfDict.filter { dict in dict["1"] }.first +``` + +```swift +↓myListOfDict.filter { $0["someString"] }.first +``` \ No newline at end of file diff --git a/docs/description/flatmap_over_map_reduce.md b/docs/description/flatmap_over_map_reduce.md new file mode 100644 index 0000000..eebfce5 --- /dev/null +++ b/docs/description/flatmap_over_map_reduce.md @@ -0,0 +1,42 @@ +# Flat Map over Map Reduce + +Prefer `flatMap` over `map` followed by `reduce([], +)` + +* **Identifier:** `flatmap_over_map_reduce` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = bar.map { $0.count }.reduce(0, +) +``` + +```swift +let foo = bar.flatMap { $0.array } +``` + +## Triggering Examples + +```swift +let foo = ↓bar.map { $0.array }.reduce([], +) +``` \ No newline at end of file diff --git a/docs/description/for_where.md b/docs/description/for_where.md new file mode 100644 index 0000000..1aa2a0e --- /dev/null +++ b/docs/description/for_where.md @@ -0,0 +1,162 @@ +# Prefer For-Where + +`where` clauses are preferred over a single `if` inside a `for` + +* **Identifier:** `for_where` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ allow_for_as_filter + + false +
+ +## Non Triggering Examples + +```swift +for user in users where user.id == 1 { } +``` + +```swift +for user in users { + if let id = user.id { } +} +``` + +```swift +for user in users { + if var id = user.id { } +} +``` + +```swift +for user in users { + if user.id == 1 { } else { } +} +``` + +```swift +for user in users { + if user.id == 1 { + } else if user.id == 2 { } +} +``` + +```swift +for user in users { + if user.id == 1 { } + print(user) +} +``` + +```swift +for user in users { + let id = user.id + if id == 1 { } +} +``` + +```swift +for user in users { + if user.id == 1 { } + return true +} +``` + +```swift +for user in users { + if user.id == 1 && user.age > 18 { } +} +``` + +```swift +for user in users { + if user.id == 1, user.age > 18 { } +} +``` + +```swift +for (index, value) in array.enumerated() { + if case .valueB(_) = value { + return index + } +} +``` + +```swift +// +// allow_for_as_filter: true +// + +for user in users { + if user.id == 1 { return true } +} + +``` + +```swift +// +// allow_for_as_filter: true +// + +for user in users { + if user.id == 1 { + let derivedValue = calculateValue(from: user) + return derivedValue != 0 + } +} + +``` + +## Triggering Examples + +```swift +for user in users { + ↓if user.id == 1 { return true } +} +``` + +```swift +for subview in subviews { + ↓if !(subview is UIStackView) { + subview.removeConstraints(subview.constraints) + subview.removeFromSuperview() + } +} +``` + +```swift +// +// allow_for_as_filter: true +// + +for subview in subviews { + ↓if !(subview is UIStackView) { + subview.removeConstraints(subview.constraints) + subview.removeFromSuperview() + } +} + +``` \ No newline at end of file diff --git a/docs/description/force_cast.md b/docs/description/force_cast.md new file mode 100644 index 0000000..c6494db --- /dev/null +++ b/docs/description/force_cast.md @@ -0,0 +1,38 @@ +# Force Cast + +Force casts should be avoided + +* **Identifier:** `force_cast` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +NSNumber() as? Int +``` + +## Triggering Examples + +```swift +NSNumber() ↓as! Int +``` \ No newline at end of file diff --git a/docs/description/force_try.md b/docs/description/force_try.md new file mode 100644 index 0000000..bd3b7dc --- /dev/null +++ b/docs/description/force_try.md @@ -0,0 +1,42 @@ +# Force Try + +Force tries should be avoided + +* **Identifier:** `force_try` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +func a() throws {} +do { + try a() +} catch {} +``` + +## Triggering Examples + +```swift +func a() throws {} +↓try! a() +``` \ No newline at end of file diff --git a/docs/description/force_unwrapping.md b/docs/description/force_unwrapping.md new file mode 100644 index 0000000..03b0216 --- /dev/null +++ b/docs/description/force_unwrapping.md @@ -0,0 +1,178 @@ +# Force Unwrapping + +Force unwrapping should be avoided + +* **Identifier:** `force_unwrapping` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +if let url = NSURL(string: query) +``` + +```swift +navigationController?.pushViewController(viewController, animated: true) +``` + +```swift +let s as! Test +``` + +```swift +try! canThrowErrors() +``` + +```swift +let object: Any! +``` + +```swift +@IBOutlet var constraints: [NSLayoutConstraint]! +``` + +```swift +setEditing(!editing, animated: true) +``` + +```swift +navigationController.setNavigationBarHidden(!navigationController.navigationBarHidden, animated: true) +``` + +```swift +if addedToPlaylist && (!self.selectedFilters.isEmpty || self.searchBar?.text?.isEmpty == false) {} +``` + +```swift +print("\(xVar)!") +``` + +```swift +var test = (!bar) +``` + +```swift +var a: [Int]! +``` + +```swift +private var myProperty: (Void -> Void)! +``` + +```swift +func foo(_ options: [AnyHashable: Any]!) { +``` + +```swift +func foo() -> [Int]! +``` + +```swift +func foo() -> [AnyHashable: Any]! +``` + +```swift +func foo() -> [Int]! { return [] } +``` + +```swift +return self +``` + +## Triggering Examples + +```swift +let url = NSURL(string: query)↓! +``` + +```swift +navigationController↓!.pushViewController(viewController, animated: true) +``` + +```swift +let unwrapped = optional↓! +``` + +```swift +return cell↓! +``` + +```swift +let url = NSURL(string: "http://www.google.com")↓! +``` + +```swift +let dict = ["Boooo": "👻"] +func bla() -> String { + return dict["Boooo"]↓! +} +``` + +```swift +let dict = ["Boooo": "👻"] +func bla() -> String { + return dict["Boooo"]↓!.contains("B") +} +``` + +```swift +let a = dict["abc"]↓!.contains("B") +``` + +```swift +dict["abc"]↓!.bar("B") +``` + +```swift +if dict["a"]↓!↓!↓!↓! {} +``` + +```swift +var foo: [Bool]! = dict["abc"]↓! +``` + +```swift +realm.objects(SwiftUTF8Object.self).filter("%K == %@", "柱нǢкƱаم👍", utf8TestString).first↓! +``` + +```swift +context("abc") { + var foo: [Bool]! = dict["abc"]↓! +} +``` + +```swift +open var computed: String { return foo.bar↓! } +``` + +```swift +return self↓! +``` + +```swift +[1, 3, 5, 6].first { $0.isMultiple(of: 2) }↓! +``` + +```swift +map["a"]↓!↓! +``` \ No newline at end of file diff --git a/docs/description/function_body_length.md b/docs/description/function_body_length.md new file mode 100644 index 0000000..1c259a4 --- /dev/null +++ b/docs/description/function_body_length.md @@ -0,0 +1,34 @@ +# Function Body Length + +Function bodies should not span too many lines + +* **Identifier:** `function_body_length` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ warning + + 50 +
+ error + + 100 +
\ No newline at end of file diff --git a/docs/description/function_default_parameter_at_end.md b/docs/description/function_default_parameter_at_end.md new file mode 100644 index 0000000..fa99b03 --- /dev/null +++ b/docs/description/function_default_parameter_at_end.md @@ -0,0 +1,133 @@ +# Function Default Parameter at End + +Prefer to locate parameters with defaults toward the end of the parameter list + +* **Identifier:** `function_default_parameter_at_end` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ ignore_first_isolation_inheritance_parameter + + true +
+ +## Non Triggering Examples + +```swift +func foo(baz: String, bar: Int = 0) {} +``` + +```swift +func foo(x: String, y: Int = 0, z: CGFloat = 0) {} +``` + +```swift +func foo(bar: String, baz: Int = 0, z: () -> Void) {} +``` + +```swift +func foo(bar: String, z: () -> Void, baz: Int = 0) {} +``` + +```swift +func foo(bar: Int = 0) {} +``` + +```swift +func foo() {} +``` + +```swift +class A: B { + override func foo(bar: Int = 0, baz: String) {} +``` + +```swift +func foo(bar: Int = 0, completion: @escaping CompletionHandler) {} +``` + +```swift +func foo(a: Int, b: CGFloat = 0) { + let block = { (error: Error?) in } +} +``` + +```swift +func foo(a: String, b: String? = nil, + c: String? = nil, d: @escaping AlertActionHandler = { _ in }) {} +``` + +```swift +override init?(for date: Date = Date(), coordinate: CLLocationCoordinate2D) {} +``` + +```swift +func handleNotification(_ userInfo: NSDictionary, + userInteraction: Bool = false, + completionHandler: ((UIBackgroundFetchResult) -> Void)?) {} +``` + +```swift +func write(withoutNotifying tokens: [NotificationToken] = {}, _ block: (() throws -> Int)) {} +``` + +```swift +func foo(bar: Int, baz: Int = 0, z: () -> Void) {} +``` + +```swift +func foo(bar: Int, baz: Int = 0, z: () -> Void, x: Int = 0) {} +``` + +```swift +func foo(isolation: isolated (any Actor)? = #isolation, bar: String) {} +``` + +## Triggering Examples + +```swift +func foo(↓bar: Int = 0, baz: String) {} +``` + +```swift +private func foo(↓bar: Int = 0, baz: String) {} +``` + +```swift +public init?(↓for date: Date = Date(), coordinate: CLLocationCoordinate2D) {} +``` + +```swift +func foo(bar: Int, ↓baz: Int = 0, z: () -> Void, x: Int) {} +``` + +```swift +// +// ignore_first_isolation_inheritance_parameter: false +// + +func foo(isolation: isolated (any Actor)? = #isolation, bar: String) {} + +``` \ No newline at end of file diff --git a/docs/description/function_parameter_count.md b/docs/description/function_parameter_count.md new file mode 100644 index 0000000..5e70bdb --- /dev/null +++ b/docs/description/function_parameter_count.md @@ -0,0 +1,105 @@ +# Function Parameter Count + +Number of function parameters should be low. + +* **Identifier:** `function_parameter_count` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 5 +
+ error + + 8 +
+ ignores_default_parameters + + true +
+ +## Non Triggering Examples + +```swift +init(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +init (a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +`init`(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +init?(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +init?(a: T, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +init?(a: T, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +func f2(p1: Int, p2: Int) { } +``` + +```swift +func f(a: Int, b: Int, c: Int, d: Int, x: Int = 42) {} +``` + +```swift +func f(a: [Int], b: Int, c: Int, d: Int, f: Int) -> [Int] { + let s = a.flatMap { $0 as? [String: Int] } ?? []}} +``` + +```swift +override func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +## Triggering Examples + +```swift +↓func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +↓func initialValue(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} +``` + +```swift +private ↓func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int = 2, g: Int) {} +``` + +```swift +struct Foo { + init(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} + ↓func bar(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}} +``` \ No newline at end of file diff --git a/docs/description/generic_type_name.md b/docs/description/generic_type_name.md new file mode 100644 index 0000000..8371dc3 --- /dev/null +++ b/docs/description/generic_type_name.md @@ -0,0 +1,258 @@ +# Generic Type Name + +Generic type name should only contain alphanumeric characters, start with an uppercase character and span between 1 and 20 characters in length. + +* **Identifier:** `generic_type_name` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ min_length + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 1 +
+ error + + 0 +
+
+ max_length + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 20 +
+ error + + 1000 +
+
+ excluded + + [] +
+ allowed_symbols + + [] +
+ unallowed_symbols_severity + + error +
+ validates_start_with_lowercase + + error +
+ +## Non Triggering Examples + +```swift +func foo() {} +``` + +```swift +func foo() -> T {} +``` + +```swift +func foo(param: U) -> T {} +``` + +```swift +func foo(param: U) -> T {} +``` + +```swift +struct Foo {} +``` + +```swift +class Foo {} +``` + +```swift +enum Foo {} +``` + +```swift +func run(_ options: NoOptions>) {} +``` + +```swift +func foo(_ options: Set) {} +``` + +```swift +func < (lhs: T?, rhs: T?) -> Bool +``` + +```swift +func configureWith(data: Either) +``` + +```swift +typealias StringDictionary = Dictionary +``` + +```swift +typealias BackwardTriple = (T3, T2, T1) +``` + +```swift +typealias DictionaryOfStrings = Dictionary +``` + +## Triggering Examples + +```swift +func foo<↓T_Foo>() {} +``` + +```swift +func foo(param: U_Foo) -> T {} +``` + +```swift +func foo<↓TTTTTTTTTTTTTTTTTTTTT>() {} +``` + +```swift +func foo<↓type>() {} +``` + +```swift +typealias StringDictionary<↓T_Foo> = Dictionary +``` + +```swift +typealias BackwardTriple = (T3, T2_Bar, T1) +``` + +```swift +typealias DictionaryOfStrings<↓T_Foo: Hashable> = Dictionary +``` + +```swift +class Foo<↓T_Foo> {} +``` + +```swift +class Foo {} +``` + +```swift +class Foo<↓T_Foo, ↓U_Foo> {} +``` + +```swift +class Foo<↓TTTTTTTTTTTTTTTTTTTTT> {} +``` + +```swift +class Foo<↓type> {} +``` + +```swift +struct Foo<↓T_Foo> {} +``` + +```swift +struct Foo {} +``` + +```swift +struct Foo<↓T_Foo, ↓U_Foo> {} +``` + +```swift +struct Foo<↓TTTTTTTTTTTTTTTTTTTTT> {} +``` + +```swift +struct Foo<↓type> {} +``` + +```swift +enum Foo<↓T_Foo> {} +``` + +```swift +enum Foo {} +``` + +```swift +enum Foo<↓T_Foo, ↓U_Foo> {} +``` + +```swift +enum Foo<↓TTTTTTTTTTTTTTTTTTTTT> {} +``` + +```swift +enum Foo<↓type> {} +``` \ No newline at end of file diff --git a/docs/description/ibinspectable_in_extension.md b/docs/description/ibinspectable_in_extension.md new file mode 100644 index 0000000..3416848 --- /dev/null +++ b/docs/description/ibinspectable_in_extension.md @@ -0,0 +1,42 @@ +# IBInspectable in Extension + +Extensions shouldn't add @IBInspectable properties + +* **Identifier:** `ibinspectable_in_extension` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Foo { + @IBInspectable private var x: Int +} +``` + +## Triggering Examples + +```swift +extension Foo { + ↓@IBInspectable private var x: Int +} +``` \ No newline at end of file diff --git a/docs/description/identical_operands.md b/docs/description/identical_operands.md new file mode 100644 index 0000000..262286b --- /dev/null +++ b/docs/description/identical_operands.md @@ -0,0 +1,984 @@ +# Identical Operands + +Comparing two identical operands is likely a mistake + +* **Identifier:** `identical_operands` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +1 == 2 +``` + +```swift +foo == bar +``` + +```swift +prefixedFoo == foo +``` + +```swift +foo.aProperty == foo.anotherProperty +``` + +```swift +self.aProperty == self.anotherProperty +``` + +```swift +"1 == 1" +``` + +```swift +self.aProperty == aProperty +``` + +```swift +lhs.aProperty == rhs.aProperty +``` + +```swift +lhs.identifier == rhs.identifier +``` + +```swift +i == index +``` + +```swift +$0 == 0 +``` + +```swift +keyValues?.count ?? 0 == 0 +``` + +```swift +string == string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num == num?.byteSwapped +``` + +```swift +num == num!.byteSwapped +``` + +```swift +1 + 1 == 1 + 2 +``` + +```swift +f( i : 2) == f (i: 3 ) +``` + +```swift +1 != 2 +``` + +```swift +foo != bar +``` + +```swift +prefixedFoo != foo +``` + +```swift +foo.aProperty != foo.anotherProperty +``` + +```swift +self.aProperty != self.anotherProperty +``` + +```swift +"1 != 1" +``` + +```swift +self.aProperty != aProperty +``` + +```swift +lhs.aProperty != rhs.aProperty +``` + +```swift +lhs.identifier != rhs.identifier +``` + +```swift +i != index +``` + +```swift +$0 != 0 +``` + +```swift +keyValues?.count ?? 0 != 0 +``` + +```swift +string != string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num != num?.byteSwapped +``` + +```swift +num != num!.byteSwapped +``` + +```swift +1 + 1 != 1 + 2 +``` + +```swift +f( i : 2) != f (i: 3 ) +``` + +```swift +1 === 2 +``` + +```swift +foo === bar +``` + +```swift +prefixedFoo === foo +``` + +```swift +foo.aProperty === foo.anotherProperty +``` + +```swift +self.aProperty === self.anotherProperty +``` + +```swift +"1 === 1" +``` + +```swift +self.aProperty === aProperty +``` + +```swift +lhs.aProperty === rhs.aProperty +``` + +```swift +lhs.identifier === rhs.identifier +``` + +```swift +i === index +``` + +```swift +$0 === 0 +``` + +```swift +keyValues?.count ?? 0 === 0 +``` + +```swift +string === string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num === num?.byteSwapped +``` + +```swift +num === num!.byteSwapped +``` + +```swift +1 + 1 === 1 + 2 +``` + +```swift +f( i : 2) === f (i: 3 ) +``` + +```swift +1 !== 2 +``` + +```swift +foo !== bar +``` + +```swift +prefixedFoo !== foo +``` + +```swift +foo.aProperty !== foo.anotherProperty +``` + +```swift +self.aProperty !== self.anotherProperty +``` + +```swift +"1 !== 1" +``` + +```swift +self.aProperty !== aProperty +``` + +```swift +lhs.aProperty !== rhs.aProperty +``` + +```swift +lhs.identifier !== rhs.identifier +``` + +```swift +i !== index +``` + +```swift +$0 !== 0 +``` + +```swift +keyValues?.count ?? 0 !== 0 +``` + +```swift +string !== string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num !== num?.byteSwapped +``` + +```swift +num !== num!.byteSwapped +``` + +```swift +1 + 1 !== 1 + 2 +``` + +```swift +f( i : 2) !== f (i: 3 ) +``` + +```swift +1 > 2 +``` + +```swift +foo > bar +``` + +```swift +prefixedFoo > foo +``` + +```swift +foo.aProperty > foo.anotherProperty +``` + +```swift +self.aProperty > self.anotherProperty +``` + +```swift +"1 > 1" +``` + +```swift +self.aProperty > aProperty +``` + +```swift +lhs.aProperty > rhs.aProperty +``` + +```swift +lhs.identifier > rhs.identifier +``` + +```swift +i > index +``` + +```swift +$0 > 0 +``` + +```swift +keyValues?.count ?? 0 > 0 +``` + +```swift +string > string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num > num?.byteSwapped +``` + +```swift +num > num!.byteSwapped +``` + +```swift +1 + 1 > 1 + 2 +``` + +```swift +f( i : 2) > f (i: 3 ) +``` + +```swift +1 >= 2 +``` + +```swift +foo >= bar +``` + +```swift +prefixedFoo >= foo +``` + +```swift +foo.aProperty >= foo.anotherProperty +``` + +```swift +self.aProperty >= self.anotherProperty +``` + +```swift +"1 >= 1" +``` + +```swift +self.aProperty >= aProperty +``` + +```swift +lhs.aProperty >= rhs.aProperty +``` + +```swift +lhs.identifier >= rhs.identifier +``` + +```swift +i >= index +``` + +```swift +$0 >= 0 +``` + +```swift +keyValues?.count ?? 0 >= 0 +``` + +```swift +string >= string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num >= num?.byteSwapped +``` + +```swift +num >= num!.byteSwapped +``` + +```swift +1 + 1 >= 1 + 2 +``` + +```swift +f( i : 2) >= f (i: 3 ) +``` + +```swift +1 < 2 +``` + +```swift +foo < bar +``` + +```swift +prefixedFoo < foo +``` + +```swift +foo.aProperty < foo.anotherProperty +``` + +```swift +self.aProperty < self.anotherProperty +``` + +```swift +"1 < 1" +``` + +```swift +self.aProperty < aProperty +``` + +```swift +lhs.aProperty < rhs.aProperty +``` + +```swift +lhs.identifier < rhs.identifier +``` + +```swift +i < index +``` + +```swift +$0 < 0 +``` + +```swift +keyValues?.count ?? 0 < 0 +``` + +```swift +string < string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num < num?.byteSwapped +``` + +```swift +num < num!.byteSwapped +``` + +```swift +1 + 1 < 1 + 2 +``` + +```swift +f( i : 2) < f (i: 3 ) +``` + +```swift +1 <= 2 +``` + +```swift +foo <= bar +``` + +```swift +prefixedFoo <= foo +``` + +```swift +foo.aProperty <= foo.anotherProperty +``` + +```swift +self.aProperty <= self.anotherProperty +``` + +```swift +"1 <= 1" +``` + +```swift +self.aProperty <= aProperty +``` + +```swift +lhs.aProperty <= rhs.aProperty +``` + +```swift +lhs.identifier <= rhs.identifier +``` + +```swift +i <= index +``` + +```swift +$0 <= 0 +``` + +```swift +keyValues?.count ?? 0 <= 0 +``` + +```swift +string <= string.lowercased() +``` + +```swift +let num: Int? = 0 +_ = num != nil && num <= num?.byteSwapped +``` + +```swift +num <= num!.byteSwapped +``` + +```swift +1 + 1 <= 1 + 2 +``` + +```swift +f( i : 2) <= f (i: 3 ) +``` + +```swift +func evaluate(_ mode: CommandMode) -> Result>> +``` + +```swift +let array = Array>() +``` + +```swift +guard Set(identifiers).count != identifiers.count else { return } +``` + +```swift +expect("foo") == "foo" +``` + +```swift +type(of: model).cachePrefix == cachePrefix +``` + +```swift +histogram[156].0 == 0x003B8D96 && histogram[156].1 == 1 +``` + +```swift +[Wrapper(type: .three), Wrapper(type: .one)].sorted { "\($0.type)" > "\($1.type)"} +``` + +```swift +array.sorted { "\($0)" < "\($1)" } +``` + +## Triggering Examples + +```swift +↓1 == 1 +``` + +```swift +↓foo == foo +``` + +```swift +↓foo.aProperty == foo.aProperty +``` + +```swift +↓self.aProperty == self.aProperty +``` + +```swift +↓$0 == $0 +``` + +```swift +↓a?.b == a?.b +``` + +```swift +if (↓elem == elem) {} +``` + +```swift +XCTAssertTrue(↓s3 == s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView == tab.webView +``` + +```swift +↓1 + 1 == 1 + 1 +``` + +```swift + ↓f( i : 2) == f (i: + 2 ) +``` + +```swift +↓1 != 1 +``` + +```swift +↓foo != foo +``` + +```swift +↓foo.aProperty != foo.aProperty +``` + +```swift +↓self.aProperty != self.aProperty +``` + +```swift +↓$0 != $0 +``` + +```swift +↓a?.b != a?.b +``` + +```swift +if (↓elem != elem) {} +``` + +```swift +XCTAssertTrue(↓s3 != s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView != tab.webView +``` + +```swift +↓1 + 1 != 1 + 1 +``` + +```swift + ↓f( i : 2) != f (i: + 2 ) +``` + +```swift +↓1 === 1 +``` + +```swift +↓foo === foo +``` + +```swift +↓foo.aProperty === foo.aProperty +``` + +```swift +↓self.aProperty === self.aProperty +``` + +```swift +↓$0 === $0 +``` + +```swift +↓a?.b === a?.b +``` + +```swift +if (↓elem === elem) {} +``` + +```swift +XCTAssertTrue(↓s3 === s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView === tab.webView +``` + +```swift +↓1 + 1 === 1 + 1 +``` + +```swift + ↓f( i : 2) === f (i: + 2 ) +``` + +```swift +↓1 !== 1 +``` + +```swift +↓foo !== foo +``` + +```swift +↓foo.aProperty !== foo.aProperty +``` + +```swift +↓self.aProperty !== self.aProperty +``` + +```swift +↓$0 !== $0 +``` + +```swift +↓a?.b !== a?.b +``` + +```swift +if (↓elem !== elem) {} +``` + +```swift +XCTAssertTrue(↓s3 !== s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView !== tab.webView +``` + +```swift +↓1 + 1 !== 1 + 1 +``` + +```swift + ↓f( i : 2) !== f (i: + 2 ) +``` + +```swift +↓1 > 1 +``` + +```swift +↓foo > foo +``` + +```swift +↓foo.aProperty > foo.aProperty +``` + +```swift +↓self.aProperty > self.aProperty +``` + +```swift +↓$0 > $0 +``` + +```swift +↓a?.b > a?.b +``` + +```swift +if (↓elem > elem) {} +``` + +```swift +XCTAssertTrue(↓s3 > s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView > tab.webView +``` + +```swift +↓1 + 1 > 1 + 1 +``` + +```swift + ↓f( i : 2) > f (i: + 2 ) +``` + +```swift +↓1 >= 1 +``` + +```swift +↓foo >= foo +``` + +```swift +↓foo.aProperty >= foo.aProperty +``` + +```swift +↓self.aProperty >= self.aProperty +``` + +```swift +↓$0 >= $0 +``` + +```swift +↓a?.b >= a?.b +``` + +```swift +if (↓elem >= elem) {} +``` + +```swift +XCTAssertTrue(↓s3 >= s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView >= tab.webView +``` + +```swift +↓1 + 1 >= 1 + 1 +``` + +```swift + ↓f( i : 2) >= f (i: + 2 ) +``` + +```swift +↓1 < 1 +``` + +```swift +↓foo < foo +``` + +```swift +↓foo.aProperty < foo.aProperty +``` + +```swift +↓self.aProperty < self.aProperty +``` + +```swift +↓$0 < $0 +``` + +```swift +↓a?.b < a?.b +``` + +```swift +if (↓elem < elem) {} +``` + +```swift +XCTAssertTrue(↓s3 < s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView < tab.webView +``` + +```swift +↓1 + 1 < 1 + 1 +``` + +```swift + ↓f( i : 2) < f (i: + 2 ) +``` + +```swift +↓1 <= 1 +``` + +```swift +↓foo <= foo +``` + +```swift +↓foo.aProperty <= foo.aProperty +``` + +```swift +↓self.aProperty <= self.aProperty +``` + +```swift +↓$0 <= $0 +``` + +```swift +↓a?.b <= a?.b +``` + +```swift +if (↓elem <= elem) {} +``` + +```swift +XCTAssertTrue(↓s3 <= s3) +``` + +```swift +if let tab = tabManager.selectedTab, ↓tab.webView <= tab.webView +``` + +```swift +↓1 + 1 <= 1 + 1 +``` + +```swift + ↓f( i : 2) <= f (i: + 2 ) +``` + +```swift + return ↓lhs.foo == lhs.foo && + lhs.bar == rhs.bar +``` + +```swift + return lhs.foo == rhs.foo && + ↓lhs.bar == lhs.bar +``` \ No newline at end of file diff --git a/docs/description/identifier_name.md b/docs/description/identifier_name.md new file mode 100644 index 0000000..8430af6 --- /dev/null +++ b/docs/description/identifier_name.md @@ -0,0 +1,330 @@ +# Identifier Name + +Identifier names should only contain alphanumeric characters and start with a lowercase character or should only contain capital letters. In an exception to the above, variable names may start with a capital letter when they are declared as static. Variable names should not be too long or too short. + +* **Identifier:** `identifier_name` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ min_length + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 3 +
+ error + + 2 +
+
+ max_length + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 40 +
+ error + + 60 +
+
+ excluded + + ["^id$"] +
+ allowed_symbols + + [] +
+ unallowed_symbols_severity + + error +
+ validates_start_with_lowercase + + error +
+ additional_operators + + ["!", "%", "&", "*", "+", "-", ".", "/", "<", "=", ">", "?", "^", "|", "~"] +
+ +## Non Triggering Examples + +```swift +let myLet = 0 +``` + +```swift +var myVar = 0 +``` + +```swift +private let _myLet = 0 +``` + +```swift +private func _myFunc() {} +``` + +```swift +fileprivate let _myLet = 0 +``` + +```swift +fileprivate func _myFunc() {} +``` + +```swift +fileprivate func _myFunc() {} +``` + +```swift +class Abc { static let MyLet = 0 } +``` + +```swift +let URL: NSURL? = nil +``` + +```swift +let XMLString: String? = nil +``` + +```swift +override var i = 0 +``` + +```swift +enum Foo { case myEnum } +``` + +```swift +func isOperator(name: String) -> Bool +``` + +```swift +func typeForKind(_ kind: SwiftDeclarationKind) -> String +``` + +```swift +func == (lhs: SyntaxToken, rhs: SyntaxToken) -> Bool +``` + +```swift +override func IsOperator(name: String) -> Bool +``` + +```swift +enum Foo { case `private` } +``` + +```swift +enum Foo { case value(String) } +``` + +```swift +f { $abc in } +``` + +```swift +class Foo { + static let Bar = 0 +} +``` + +```swift +class Foo { + static var Bar = 0 +} +``` + +```swift +// +// additional_operators: ["!", "%", "&", "*", "+", "-", ".", "/", "<", "=", ">", "?", "^", "|", "~", "√"] +// + +func √ (arg: Double) -> Double { arg } + +``` + +## Triggering Examples + +```swift +class C { static let ↓_myLet = 0 } +``` + +```swift +class C { class let ↓MyLet = 0 } +``` + +```swift +class C { static func ↓MyFunc() {} } +``` + +```swift +class C { class func ↓MyFunc() {} } +``` + +```swift +private let ↓myLet_ = 0 +``` + +```swift +let ↓myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0 +``` + +```swift +var ↓myExtremelyVeryVeryVeryVeryVeryVeryLongVar = 0 +``` + +```swift +private let ↓_myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0 +``` + +```swift +let ↓i = 0 +``` + +```swift +var ↓aa = 0 +``` + +```swift +private let ↓_i = 0 +``` + +```swift +if let ↓_x {} +``` + +```swift +guard var ↓x = x else {} +``` + +```swift +func myFunc( + _ ↓s: String, + i ↓j: Int, + _ goodName: Double, + name ↓n: String, + ↓x: Int, + abc: Double, + _: Double, + last _: Double +) {} +``` + +```swift +let (↓a, abc) = (1, 1) +``` + +```swift +if let ↓i {} +``` + +```swift +for ↓i in [] {} +``` + +```swift +f { ↓x in } +``` + +```swift +f { ↓$x in } +``` + +```swift +f { (x abc: Int, _ ↓x: Int) in } +``` + +```swift +enum E { + case ↓c + case case1(Int) + case case2(↓a: Int) + case case3(_ ↓a: Int) +} +``` + +```swift +class C { + var ↓x: Int { + get { 1 } + set(↓y) { x = y } + } +} +``` + +```swift +func ↓√ (arg: Double) -> Double { arg } +``` \ No newline at end of file diff --git a/docs/description/implicit_getter.md b/docs/description/implicit_getter.md new file mode 100644 index 0000000..4378d15 --- /dev/null +++ b/docs/description/implicit_getter.md @@ -0,0 +1,321 @@ +# Implicit Getter + +Computed read-only properties and subscripts should avoid using the get keyword. + +* **Identifier:** `implicit_getter` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Foo { + var foo: Int { + get { return 3 } + set { _abc = newValue } + } +} +``` + +```swift +class Foo { + var foo: Int { + return 20 + } +} +``` + +```swift +class Foo { + static var foo: Int { + return 20 + } +} +``` + +```swift +class Foo { + static var foo: Int { + get { return 3 } + set { _abc = newValue } + } +} +``` + +```swift +class Foo { + var foo: Int { + get { _foo } + _modify { yield &_foo } + } +} +``` + +```swift +class Foo { + var _foo: Int + var foo: Int { + @storageRestrictions(initializes: _foo) + init { _foo = newValue } + get { _foo } + } +} +``` + +```swift +class Foo { + var foo: Int +} +``` + +```swift +class Foo { + var foo: Int { + return getValueFromDisk() + } +} +``` + +```swift +class Foo { + var foo: String { + return "get" + } +} +``` + +```swift +protocol Foo { + var foo: Int { get } +} +``` + +```swift +protocol Foo { + var foo: Int { get set } +} +``` + +```swift +class Foo { + var foo: Int { + struct Bar { + var bar: Int { + get { return 1 } + set { _ = newValue } + } + } + + return Bar().bar + } +} +``` + +```swift +var _objCTaggedPointerBits: UInt { + @inline(__always) get { return 0 } +} +``` + +```swift +var next: Int? { + mutating get { + defer { self.count += 1 } + return self.count + } +} +``` + +```swift +extension Foo { + var bar: Bool { + get { _bar } + set { self._bar = newValue } + } +} +``` + +```swift +extension Foo { + var bar: Bool { + get { _bar } + set(newValue) { self._bar = newValue } + } +} +``` + +```swift +extension Float { + var clamped: Float { + set { + self = min(1, max(0, newValue)) + } + get { + min(1, max(0, self)) + } + } +} +``` + +```swift +extension Reactive where Base: UITapGestureRecognizer { + var tapped: CocoaAction? { + get { + return associatedAction.withValue { $0.flatMap { $0.action } } + } + nonmutating set { + setAction(newValue) + } + } +} +``` + +```swift +extension Test { + var foo: Bool { + get { + bar?.boolValue ?? true // Comment mentioning word set which triggers violation + } + set { + bar = NSNumber(value: newValue as Bool) + } + } +} +``` + +```swift +class Foo { + subscript(i: Int) -> Int { + return 20 + } +} +``` + +```swift +class Foo { + subscript(i: Int) -> Int { + get { return 3 } + set { _abc = newValue } + } +} +``` + +```swift +protocol Foo { + subscript(i: Int) -> Int { get } +} +``` + +```swift +protocol Foo { + subscript(i: Int) -> Int { get set } +} +``` + +```swift +class DatabaseEntity { + var isSynced: Bool { + get async { + await database.isEntitySynced(self) + } + } +} +``` + +```swift +struct Test { + subscript(value: Int) -> Int { + get throws { + if value == 0 { + throw NSError() + } else { + return value + } + } + } +} +``` + +## Triggering Examples + +```swift +class Foo { + var foo: Int { + ↓get { + return 20 + } + } +} +``` + +```swift +class Foo { + var foo: Int { + ↓get{ return 20 } + } +} +``` + +```swift +class Foo { + static var foo: Int { + ↓get { + return 20 + } + } +} +``` + +```swift +var foo: Int { + ↓get { return 20 } +} +``` + +```swift +class Foo { + @objc func bar() {} + var foo: Int { + ↓get { + return 20 + } + } +} +``` + +```swift +extension Foo { + var bar: Bool { + ↓get { _bar } + } +} +``` + +```swift +class Foo { + subscript(i: Int) -> Int { + ↓get { + return 20 + } + } +} +``` \ No newline at end of file diff --git a/docs/description/implicit_return.md b/docs/description/implicit_return.md new file mode 100644 index 0000000..2fe6d9b --- /dev/null +++ b/docs/description/implicit_return.md @@ -0,0 +1,236 @@ +# Implicit Return + +Prefer implicit returns in closures, functions and getters + +* **Identifier:** `implicit_return` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ included + + [closure, function, getter, initializer, subscript] +
+ +## Non Triggering Examples + +```swift +foo.map { $0 + 1 } +``` + +```swift +foo.map({ $0 + 1 }) +``` + +```swift +foo.map { value in value + 1 } +``` + +```swift +[1, 2].first(where: { + true +}) +``` + +```swift +func foo() -> Int { + 0 +} +``` + +```swift +class Foo { + func foo() -> Int { 0 } +} +``` + +```swift +func fetch() -> Data? { + do { + return try loadData() + } catch { + return nil + } +} +``` + +```swift +func f() -> Int { + let i = 4 + return i +} +``` + +```swift +func f() -> Int { + return 3 + let i = 2 +} +``` + +```swift +func f() -> Int { + return g() + func g() -> Int { 4 } +} +``` + +```swift +var foo: Bool { true } +``` + +```swift +class Foo { + var bar: Int { + get { + 0 + } + } +} +``` + +```swift +class Foo { + static var bar: Int { + 0 + } +} +``` + +```swift +class C { + let i: Int + init(i: Int) { + if i < 3 { + self.i = 1 + return + } + self.i = 2 + } +} +``` + +```swift +class C { + init?() { + let i = 1 + return nil + } +} +``` + +```swift +class C { + subscript(i: Int) -> Int { + let res = i + return res + } +} +``` + +## Triggering Examples + +```swift +foo.map { value in + ↓return value + 1 +} +``` + +```swift +foo.map { + ↓return $0 + 1 +} +``` + +```swift +foo.map({ ↓return $0 + 1}) +``` + +```swift +[1, 2].first(where: { + ↓return true +}) +``` + +```swift +func foo() -> Int { + ↓return 0 +} +``` + +```swift +class Foo { + func foo() -> Int { ↓return 0 } +} +``` + +```swift +func f() { ↓return } +``` + +```swift +var foo: Bool { ↓return true } +``` + +```swift +class Foo { + var bar: Int { + get { + ↓return 0 + } + } +} +``` + +```swift +class Foo { + static var bar: Int { + ↓return 0 + } +} +``` + +```swift +class C { + init() { + ↓return + } +} +``` + +```swift +class C { + init?() { + ↓return nil + } +} +``` + +```swift +class C { + subscript(i: Int) -> Int { + ↓return i + } +} +``` \ No newline at end of file diff --git a/docs/description/implicitly_unwrapped_optional.md b/docs/description/implicitly_unwrapped_optional.md new file mode 100644 index 0000000..6a136d1 --- /dev/null +++ b/docs/description/implicitly_unwrapped_optional.md @@ -0,0 +1,108 @@ +# Implicitly Unwrapped Optional + +Implicitly unwrapped optionals should be avoided when possible + +* **Identifier:** `implicitly_unwrapped_optional` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ mode + + all_except_iboutlets +
+ +## Non Triggering Examples + +```swift +@IBOutlet private var label: UILabel! +``` + +```swift +@IBOutlet var label: UILabel! +``` + +```swift +@IBOutlet var label: [UILabel!] +``` + +```swift +if !boolean {} +``` + +```swift +let int: Int? = 42 +``` + +```swift +let int: Int? = nil +``` + +## Triggering Examples + +```swift +let label: ↓UILabel! +``` + +```swift +let IBOutlet: ↓UILabel! +``` + +```swift +let labels: [↓UILabel!] +``` + +```swift +var ints: [↓Int!] = [42, nil, 42] +``` + +```swift +let label: ↓IBOutlet! +``` + +```swift +let int: ↓Int! = 42 +``` + +```swift +let int: ↓Int! = nil +``` + +```swift +var int: ↓Int! = 42 +``` + +```swift +let collection: AnyCollection<↓Int!> +``` + +```swift +func foo(int: ↓Int!) {} +``` + +```swift +class MyClass { + weak var bar: ↓SomeObject! +} +``` \ No newline at end of file diff --git a/docs/description/inclusive_language.md b/docs/description/inclusive_language.md new file mode 100644 index 0000000..602f05b --- /dev/null +++ b/docs/description/inclusive_language.md @@ -0,0 +1,86 @@ +# Inclusive Language + +Identifiers should use inclusive language that avoids discrimination against groups of people based on race, gender, or socioeconomic status. + +* **Identifier:** `inclusive_language` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = "abc" +``` + +```swift +enum AllowList { + case foo, bar +} +``` + +```swift +func updateAllowList(add: String) {} +``` + +```swift +enum WalletItemType { + case visa + case mastercard +} +``` + +```swift +func chargeMasterCard(_ card: Card) {} +``` + +## Triggering Examples + +```swift +let ↓slave = "abc" +``` + +```swift +enum ↓BlackList { + case foo, bar +} +``` + +```swift +func ↓updateWhiteList(add: String) {} +``` + +```swift +enum ListType { + case ↓whitelist + case ↓blacklist +} +``` + +```swift +init(↓master: String, ↓slave: String) {} +``` + +```swift +final class FooBar { + func register<↓Master, ↓Slave>(one: Master, two: Slave) {} +} +``` \ No newline at end of file diff --git a/docs/description/indentation_width.md b/docs/description/indentation_width.md new file mode 100644 index 0000000..5ee8f8e --- /dev/null +++ b/docs/description/indentation_width.md @@ -0,0 +1,118 @@ +# Indentation Width + +Indent code using either one tab or the configured amount of spaces, unindent to match previous indentations. Don't indent the first line. + +* **Identifier:** `indentation_width` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ indentation_width + + 4 +
+ include_comments + + true +
+ include_compiler_directives + + true +
+ include_multiline_strings + + true +
+ +## Non Triggering Examples + +```swift +firstLine +secondLine +``` + +```swift +firstLine + secondLine +``` + +```swift +firstLine + secondLine + thirdLine + + fourthLine +``` + +```swift +firstLine + secondLine + thirdLine + //test + fourthLine +``` + +```swift +firstLine + secondLine + thirdLine +fourthLine +``` + +## Triggering Examples + +```swift +↓ firstLine +``` + +```swift +firstLine + secondLine +``` + +```swift +firstLine + secondLine + +↓ fourthLine +``` + +```swift +firstLine + secondLine + thirdLine +↓ fourthLine +``` \ No newline at end of file diff --git a/docs/description/inert_defer.md b/docs/description/inert_defer.md new file mode 100644 index 0000000..b369fea --- /dev/null +++ b/docs/description/inert_defer.md @@ -0,0 +1,69 @@ +# Inert Defer + +If defer is at the end of its parent scope, it will be executed right where it is anyway + +* **Identifier:** `inert_defer` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func example3() { + defer { /* deferred code */ } + + print("other code") +} +``` + +```swift +func example4() { + if condition { + defer { /* deferred code */ } + print("other code") + } +} +``` + +## Triggering Examples + +```swift +func example0() { + ↓defer { /* deferred code */ } +} +``` + +```swift +func example1() { + ↓defer { /* deferred code */ } + // comment +} +``` + +```swift +func example2() { + if condition { + ↓defer { /* deferred code */ } + // comment + } +} +``` \ No newline at end of file diff --git a/docs/description/invalid_swiftlint_command.md b/docs/description/invalid_swiftlint_command.md new file mode 100644 index 0000000..5b3bde3 --- /dev/null +++ b/docs/description/invalid_swiftlint_command.md @@ -0,0 +1,114 @@ +# Invalid SwiftLint Command + +swiftlint command is invalid + +* **Identifier:** `invalid_swiftlint_command` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +// swiftlint:disable unused_import +``` + +```swift +// swiftlint:enable unused_import +``` + +```swift +// swiftlint:disable:next unused_import +``` + +```swift +// swiftlint:disable:previous unused_import +``` + +```swift +// swiftlint:disable:this unused_import +``` + +```swift +//swiftlint:disable:this unused_import +``` + +## Triggering Examples + +```swift +// ↓swiftlint: +``` + +```swift +// ↓swiftlint: +``` + +```swift +// ↓swiftlint:: +``` + +```swift +// ↓swiftlint:: +``` + +```swift +// ↓swiftlint:disable +``` + +```swift +// ↓swiftlint:dissable unused_import +``` + +```swift +// ↓swiftlint:enaaaable unused_import +``` + +```swift +// ↓swiftlint:disable:nxt unused_import +``` + +```swift +// ↓swiftlint:enable:prevus unused_import +``` + +```swift +// ↓swiftlint:enable:ths unused_import +``` + +```swift +// ↓swiftlint:enable +``` + +```swift +// ↓swiftlint:enable: +``` + +```swift +// ↓swiftlint:enable: +``` + +```swift +// ↓swiftlint:disable: unused_import +``` + +```swift +// s↓swiftlint:disable unused_import +``` \ No newline at end of file diff --git a/docs/description/is_disjoint.md b/docs/description/is_disjoint.md new file mode 100644 index 0000000..2992e51 --- /dev/null +++ b/docs/description/is_disjoint.md @@ -0,0 +1,54 @@ +# Is Disjoint + +Prefer using `Set.isDisjoint(with:)` over `Set.intersection(_:).isEmpty` + +* **Identifier:** `is_disjoint` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +_ = Set(syntaxKinds).isDisjoint(with: commentAndStringKindsSet) +``` + +```swift +let isObjc = !objcAttributes.isDisjoint(with: dictionary.enclosedSwiftAttributes) +``` + +```swift +_ = Set(syntaxKinds).intersection(commentAndStringKindsSet) +``` + +```swift +_ = !objcAttributes.intersection(dictionary.enclosedSwiftAttributes) +``` + +## Triggering Examples + +```swift +_ = Set(syntaxKinds).↓intersection(commentAndStringKindsSet).isEmpty +``` + +```swift +let isObjc = !objcAttributes.↓intersection(dictionary.enclosedSwiftAttributes).isEmpty +``` \ No newline at end of file diff --git a/docs/description/joined_default_parameter.md b/docs/description/joined_default_parameter.md new file mode 100644 index 0000000..b76074c --- /dev/null +++ b/docs/description/joined_default_parameter.md @@ -0,0 +1,57 @@ +# Joined Default Parameter + +Discouraged explicit usage of the default separator + +* **Identifier:** `joined_default_parameter` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = bar.joined() +``` + +```swift +let foo = bar.joined(separator: ",") +``` + +```swift +let foo = bar.joined(separator: toto) +``` + +## Triggering Examples + +```swift +let foo = bar.joined(↓separator: "") +``` + +```swift +let foo = bar.filter(toto) + .joined(↓separator: ""), +``` + +```swift +func foo() -> String { + return ["1", "2"].joined(↓separator: "") +} +``` \ No newline at end of file diff --git a/docs/description/large_tuple.md b/docs/description/large_tuple.md new file mode 100644 index 0000000..7e6eca0 --- /dev/null +++ b/docs/description/large_tuple.md @@ -0,0 +1,234 @@ +# Large Tuple + +Tuples shouldn't have too many members. Create a custom type instead. + +* **Identifier:** `large_tuple` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ warning + + 2 +
+ error + + 3 +
+ +## Non Triggering Examples + +```swift +let foo: (Int, Int) +``` + +```swift +let foo: (start: Int, end: Int) +``` + +```swift +let foo: (Int, (Int, String)) +``` + +```swift +func foo() -> (Int, Int) +``` + +```swift +func foo() -> (Int, Int) {} +``` + +```swift +func foo(bar: String) -> (Int, Int) +``` + +```swift +func foo(bar: String) -> (Int, Int) {} +``` + +```swift +func foo() throws -> (Int, Int) +``` + +```swift +func foo() throws -> (Int, Int) {} +``` + +```swift +let foo: (Int, Int, Int) -> Void +``` + +```swift +let foo: (Int, Int, Int) throws -> Void +``` + +```swift +func foo(bar: (Int, String, Float) -> Void) +``` + +```swift +func foo(bar: (Int, String, Float) throws -> Void) +``` + +```swift +var completionHandler: ((_ data: Data?, _ resp: URLResponse?, _ e: NSError?) -> Void)! +``` + +```swift +func getDictionaryAndInt() -> (Dictionary, Int)? +``` + +```swift +func getGenericTypeAndInt() -> (Type, Int)? +``` + +```swift +func foo() async -> (Int, Int) +``` + +```swift +func foo() async -> (Int, Int) {} +``` + +```swift +func foo(bar: String) async -> (Int, Int) +``` + +```swift +func foo(bar: String) async -> (Int, Int) {} +``` + +```swift +func foo() async throws -> (Int, Int) +``` + +```swift +func foo() async throws -> (Int, Int) {} +``` + +```swift +let foo: (Int, Int, Int) async -> Void +``` + +```swift +let foo: (Int, Int, Int) async throws -> Void +``` + +```swift +func foo(bar: (Int, String, Float) async -> Void) +``` + +```swift +func foo(bar: (Int, String, Float) async throws -> Void) +``` + +```swift +func getDictionaryAndInt() async -> (Dictionary, Int)? +``` + +```swift +func getGenericTypeAndInt() async -> (Type, Int)? +``` + +## Triggering Examples + +```swift +let foo: ↓(Int, Int, Int) +``` + +```swift +let foo: ↓(start: Int, end: Int, value: String) +``` + +```swift +let foo: (Int, ↓(Int, Int, Int)) +``` + +```swift +func foo(bar: ↓(Int, Int, Int)) +``` + +```swift +func foo() -> ↓(Int, Int, Int) +``` + +```swift +func foo() -> ↓(Int, Int, Int) {} +``` + +```swift +func foo(bar: String) -> ↓(Int, Int, Int) +``` + +```swift +func foo(bar: String) -> ↓(Int, Int, Int) {} +``` + +```swift +func foo() throws -> ↓(Int, Int, Int) +``` + +```swift +func foo() throws -> ↓(Int, Int, Int) {} +``` + +```swift +func foo() throws -> ↓(Int, ↓(String, String, String), Int) {} +``` + +```swift +func getDictionaryAndInt() -> (Dictionary, Int)? +``` + +```swift +func foo(bar: ↓(Int, Int, Int)) async +``` + +```swift +func foo() async -> ↓(Int, Int, Int) +``` + +```swift +func foo() async -> ↓(Int, Int, Int) {} +``` + +```swift +func foo(bar: String) async -> ↓(Int, Int, Int) +``` + +```swift +func foo(bar: String) async -> ↓(Int, Int, Int) {} +``` + +```swift +func foo() async throws -> ↓(Int, Int, Int) +``` + +```swift +func foo() async throws -> ↓(Int, Int, Int) {} +``` + +```swift +func foo() async throws -> ↓(Int, ↓(String, String, String), Int) {} +``` + +```swift +func getDictionaryAndInt() async -> (Dictionary, Int)? +``` \ No newline at end of file diff --git a/docs/description/last_where.md b/docs/description/last_where.md new file mode 100644 index 0000000..160564a --- /dev/null +++ b/docs/description/last_where.md @@ -0,0 +1,79 @@ +# Last Where + +Prefer using `.last(where:)` over `.filter { }.last` in collections + +* **Identifier:** `last_where` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +kinds.filter(excludingKinds.contains).isEmpty && kinds.last == .identifier +``` + +```swift +myList.last(where: { $0 % 2 == 0 }) +``` + +```swift +match(pattern: pattern).filter { $0.last == .identifier } +``` + +```swift +(myList.filter { $0 == 1 }.suffix(2)).last +``` + +```swift +collection.filter("stringCol = '3'").last +``` + +## Triggering Examples + +```swift +↓myList.filter { $0 % 2 == 0 }.last +``` + +```swift +↓myList.filter({ $0 % 2 == 0 }).last +``` + +```swift +↓myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).last +``` + +```swift +↓myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).last?.something() +``` + +```swift +↓myList.filter(someFunction).last +``` + +```swift +↓myList.filter({ $0 % 2 == 0 }) +.last +``` + +```swift +(↓myList.filter { $0 == 1 }).last +``` \ No newline at end of file diff --git a/docs/description/leading_whitespace.md b/docs/description/leading_whitespace.md new file mode 100644 index 0000000..2b31556 --- /dev/null +++ b/docs/description/leading_whitespace.md @@ -0,0 +1,43 @@ +# Leading Whitespace + +Files should not contain leading whitespace + +* **Identifier:** `leading_whitespace` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +// +``` + +## Triggering Examples + +```swift + +// +``` + +```swift + // +``` \ No newline at end of file diff --git a/docs/description/legacy_cggeometry_functions.md b/docs/description/legacy_cggeometry_functions.md new file mode 100644 index 0000000..848f588 --- /dev/null +++ b/docs/description/legacy_cggeometry_functions.md @@ -0,0 +1,190 @@ +# Legacy CGGeometry Functions + +Struct extension properties and methods are preferred over legacy functions + +* **Identifier:** `legacy_cggeometry_functions` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +rect.width +``` + +```swift +rect.height +``` + +```swift +rect.minX +``` + +```swift +rect.midX +``` + +```swift +rect.maxX +``` + +```swift +rect.minY +``` + +```swift +rect.midY +``` + +```swift +rect.maxY +``` + +```swift +rect.isNull +``` + +```swift +rect.isEmpty +``` + +```swift +rect.isInfinite +``` + +```swift +rect.standardized +``` + +```swift +rect.integral +``` + +```swift +rect.insetBy(dx: 5.0, dy: -7.0) +``` + +```swift +rect.offsetBy(dx: 5.0, dy: -7.0) +``` + +```swift +rect1.union(rect2) +``` + +```swift +rect1.intersect(rect2) +``` + +```swift +rect1.contains(rect2) +``` + +```swift +rect.contains(point) +``` + +```swift +rect1.intersects(rect2) +``` + +## Triggering Examples + +```swift +↓CGRectGetWidth(rect) +``` + +```swift +↓CGRectGetHeight(rect) +``` + +```swift +↓CGRectGetMinX(rect) +``` + +```swift +↓CGRectGetMidX(rect) +``` + +```swift +↓CGRectGetMaxX(rect) +``` + +```swift +↓CGRectGetMinY(rect) +``` + +```swift +↓CGRectGetMidY(rect) +``` + +```swift +↓CGRectGetMaxY(rect) +``` + +```swift +↓CGRectIsNull(rect) +``` + +```swift +↓CGRectIsEmpty(rect) +``` + +```swift +↓CGRectIsInfinite(rect) +``` + +```swift +↓CGRectStandardize(rect) +``` + +```swift +↓CGRectIntegral(rect) +``` + +```swift +↓CGRectInset(rect, 10, 5) +``` + +```swift +↓CGRectOffset(rect, -2, 8.3) +``` + +```swift +↓CGRectUnion(rect1, rect2) +``` + +```swift +↓CGRectIntersection(rect1, rect2) +``` + +```swift +↓CGRectContainsRect(rect1, rect2) +``` + +```swift +↓CGRectContainsPoint(rect, point) +``` + +```swift +↓CGRectIntersectsRect(rect1, rect2) +``` \ No newline at end of file diff --git a/docs/description/legacy_constant.md b/docs/description/legacy_constant.md new file mode 100644 index 0000000..4893a64 --- /dev/null +++ b/docs/description/legacy_constant.md @@ -0,0 +1,110 @@ +# Legacy Constant + +Struct-scoped constants are preferred over legacy global constants + +* **Identifier:** `legacy_constant` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +CGRect.infinite +``` + +```swift +CGPoint.zero +``` + +```swift +CGRect.zero +``` + +```swift +CGSize.zero +``` + +```swift +NSPoint.zero +``` + +```swift +NSRect.zero +``` + +```swift +NSSize.zero +``` + +```swift +CGRect.null +``` + +```swift +CGFloat.pi +``` + +```swift +Float.pi +``` + +## Triggering Examples + +```swift +↓CGRectInfinite +``` + +```swift +↓CGPointZero +``` + +```swift +↓CGRectZero +``` + +```swift +↓CGSizeZero +``` + +```swift +↓NSZeroPoint +``` + +```swift +↓NSZeroRect +``` + +```swift +↓NSZeroSize +``` + +```swift +↓CGRectNull +``` + +```swift +↓CGFloat(M_PI) +``` + +```swift +↓Float(M_PI) +``` \ No newline at end of file diff --git a/docs/description/legacy_constructor.md b/docs/description/legacy_constructor.md new file mode 100644 index 0000000..c22fa6e --- /dev/null +++ b/docs/description/legacy_constructor.md @@ -0,0 +1,215 @@ +# Legacy Constructor + +Swift constructors are preferred over legacy convenience functions + +* **Identifier:** `legacy_constructor` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +CGPoint(x: 10, y: 10) +``` + +```swift +CGPoint(x: xValue, y: yValue) +``` + +```swift +CGSize(width: 10, height: 10) +``` + +```swift +CGSize(width: aWidth, height: aHeight) +``` + +```swift +CGRect(x: 0, y: 0, width: 10, height: 10) +``` + +```swift +CGRect(x: xVal, y: yVal, width: aWidth, height: aHeight) +``` + +```swift +CGVector(dx: 10, dy: 10) +``` + +```swift +CGVector(dx: deltaX, dy: deltaY) +``` + +```swift +NSPoint(x: 10, y: 10) +``` + +```swift +NSPoint(x: xValue, y: yValue) +``` + +```swift +NSSize(width: 10, height: 10) +``` + +```swift +NSSize(width: aWidth, height: aHeight) +``` + +```swift +NSRect(x: 0, y: 0, width: 10, height: 10) +``` + +```swift +NSRect(x: xVal, y: yVal, width: aWidth, height: aHeight) +``` + +```swift +NSRange(location: 10, length: 1) +``` + +```swift +NSRange(location: loc, length: len) +``` + +```swift +UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 10) +``` + +```swift +UIEdgeInsets(top: aTop, left: aLeft, bottom: aBottom, right: aRight) +``` + +```swift +NSEdgeInsets(top: 0, left: 0, bottom: 10, right: 10) +``` + +```swift +NSEdgeInsets(top: aTop, left: aLeft, bottom: aBottom, right: aRight) +``` + +```swift +UIOffset(horizontal: 0, vertical: 10) +``` + +```swift +UIOffset(horizontal: horizontal, vertical: vertical) +``` + +## Triggering Examples + +```swift +↓CGPointMake(10, 10) +``` + +```swift +↓CGPointMake(xVal, yVal) +``` + +```swift +↓CGPointMake(calculateX(), 10) +``` + +```swift +↓CGSizeMake(10, 10) +``` + +```swift +↓CGSizeMake(aWidth, aHeight) +``` + +```swift +↓CGRectMake(0, 0, 10, 10) +``` + +```swift +↓CGRectMake(xVal, yVal, width, height) +``` + +```swift +↓CGVectorMake(10, 10) +``` + +```swift +↓CGVectorMake(deltaX, deltaY) +``` + +```swift +↓NSMakePoint(10, 10) +``` + +```swift +↓NSMakePoint(xVal, yVal) +``` + +```swift +↓NSMakeSize(10, 10) +``` + +```swift +↓NSMakeSize(aWidth, aHeight) +``` + +```swift +↓NSMakeRect(0, 0, 10, 10) +``` + +```swift +↓NSMakeRect(xVal, yVal, width, height) +``` + +```swift +↓NSMakeRange(10, 1) +``` + +```swift +↓NSMakeRange(loc, len) +``` + +```swift +↓UIEdgeInsetsMake(0, 0, 10, 10) +``` + +```swift +↓UIEdgeInsetsMake(top, left, bottom, right) +``` + +```swift +↓NSEdgeInsetsMake(0, 0, 10, 10) +``` + +```swift +↓NSEdgeInsetsMake(top, left, bottom, right) +``` + +```swift +↓CGVectorMake(10, 10) +↓NSMakeRange(10, 1) +``` + +```swift +↓UIOffsetMake(0, 10) +``` + +```swift +↓UIOffsetMake(horizontal, vertical) +``` \ No newline at end of file diff --git a/docs/description/legacy_hashing.md b/docs/description/legacy_hashing.md new file mode 100644 index 0000000..9a136f2 --- /dev/null +++ b/docs/description/legacy_hashing.md @@ -0,0 +1,97 @@ +# Legacy Hashing + +Prefer using the `hash(into:)` function instead of overriding `hashValue` + +* **Identifier:** `legacy_hashing` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +struct Foo: Hashable { + let bar: Int = 10 + + func hash(into hasher: inout Hasher) { + hasher.combine(bar) + } +} +``` + +```swift +class Foo: Hashable { + let bar: Int = 10 + + func hash(into hasher: inout Hasher) { + hasher.combine(bar) + } +} +``` + +```swift +var hashValue: Int { return 1 } +class Foo: Hashable { + } +``` + +```swift +class Foo: Hashable { + let bar: String = "Foo" + + public var hashValue: String { + return bar + } +} +``` + +```swift +class Foo: Hashable { + let bar: String = "Foo" + + public var hashValue: String { + get { return bar } + set { bar = newValue } + } +} +``` + +## Triggering Examples + +```swift +struct Foo: Hashable { + let bar: Int = 10 + + public ↓var hashValue: Int { + return bar + } +} +``` + +```swift +class Foo: Hashable { + let bar: Int = 10 + + public ↓var hashValue: Int { + return bar + } +} +``` \ No newline at end of file diff --git a/docs/description/legacy_multiple.md b/docs/description/legacy_multiple.md new file mode 100644 index 0000000..aded0e1 --- /dev/null +++ b/docs/description/legacy_multiple.md @@ -0,0 +1,89 @@ +# Legacy Multiple + +Prefer using the `isMultiple(of:)` function instead of using the remainder operator (`%`) + +* **Identifier:** `legacy_multiple` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +cell.contentView.backgroundColor = indexPath.row.isMultiple(of: 2) ? .gray : .white +``` + +```swift +guard count.isMultiple(of: 2) else { throw DecodingError.dataCorrupted(...) } +``` + +```swift +sanityCheck(bytes > 0 && bytes.isMultiple(of: 4), "capacity must be multiple of 4 bytes") +``` + +```swift +guard let i = reversedNumbers.firstIndex(where: { $0.isMultiple(of: 2) }) else { return } +``` + +```swift +let constant = 56 +let isMultiple = value.isMultiple(of: constant) +``` + +```swift +let constant = 56 +let secret = value % constant == 5 +``` + +```swift +let secretValue = (value % 3) + 2 +``` + +## Triggering Examples + +```swift +cell.contentView.backgroundColor = indexPath.row ↓% 2 == 0 ? .gray : .white +``` + +```swift +cell.contentView.backgroundColor = 0 == indexPath.row ↓% 2 ? .gray : .white +``` + +```swift +cell.contentView.backgroundColor = indexPath.row ↓% 2 != 0 ? .gray : .white +``` + +```swift +guard count ↓% 2 == 0 else { throw DecodingError.dataCorrupted(...) } +``` + +```swift +sanityCheck(bytes > 0 && bytes ↓% 4 == 0, "capacity must be multiple of 4 bytes") +``` + +```swift +guard let i = reversedNumbers.firstIndex(where: { $0 ↓% 2 == 0 }) else { return } +``` + +```swift +let constant = 56 +let isMultiple = value ↓% constant == 0 +``` \ No newline at end of file diff --git a/docs/description/legacy_nsgeometry_functions.md b/docs/description/legacy_nsgeometry_functions.md new file mode 100644 index 0000000..b29166e --- /dev/null +++ b/docs/description/legacy_nsgeometry_functions.md @@ -0,0 +1,182 @@ +# Legacy NSGeometry Functions + +Struct extension properties and methods are preferred over legacy functions + +* **Identifier:** `legacy_nsgeometry_functions` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +rect.width +``` + +```swift +rect.height +``` + +```swift +rect.minX +``` + +```swift +rect.midX +``` + +```swift +rect.maxX +``` + +```swift +rect.minY +``` + +```swift +rect.midY +``` + +```swift +rect.maxY +``` + +```swift +rect.isEmpty +``` + +```swift +rect.integral +``` + +```swift +rect.insetBy(dx: 5.0, dy: -7.0) +``` + +```swift +rect.offsetBy(dx: 5.0, dy: -7.0) +``` + +```swift +rect1.union(rect2) +``` + +```swift +rect1.intersection(rect2) +``` + +```swift +rect1.contains(rect2) +``` + +```swift +rect.contains(point) +``` + +```swift +rect1.intersects(rect2) +``` + +## Triggering Examples + +```swift +↓NSWidth(rect) +``` + +```swift +↓NSHeight(rect) +``` + +```swift +↓NSMinX(rect) +``` + +```swift +↓NSMidX(rect) +``` + +```swift +↓NSMaxX(rect) +``` + +```swift +↓NSMinY(rect) +``` + +```swift +↓NSMidY(rect) +``` + +```swift +↓NSMaxY(rect) +``` + +```swift +↓NSEqualRects(rect1, rect2) +``` + +```swift +↓NSEqualSizes(size1, size2) +``` + +```swift +↓NSEqualPoints(point1, point2) +``` + +```swift +↓NSEdgeInsetsEqual(insets2, insets2) +``` + +```swift +↓NSIsEmptyRect(rect) +``` + +```swift +↓NSIntegralRect(rect) +``` + +```swift +↓NSInsetRect(rect, 10, 5) +``` + +```swift +↓NSOffsetRect(rect, -2, 8.3) +``` + +```swift +↓NSUnionRect(rect1, rect2) +``` + +```swift +↓NSIntersectionRect(rect1, rect2) +``` + +```swift +↓NSContainsRect(rect1, rect2) +``` + +```swift +↓NSPointInRect(rect, point) +``` + +```swift +↓NSIntersectsRect(rect1, rect2) +``` \ No newline at end of file diff --git a/docs/description/legacy_objc_type.md b/docs/description/legacy_objc_type.md new file mode 100644 index 0000000..eeafee3 --- /dev/null +++ b/docs/description/legacy_objc_type.md @@ -0,0 +1,106 @@ +# Legacy Objective-C Reference Type + +Prefer Swift value types to bridged Objective-C reference types + +* **Identifier:** `legacy_objc_type` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ allowed_types + + [] +
+ +## Non Triggering Examples + +```swift +var array = Array() +``` + +```swift +var calendar: Calendar? = nil +``` + +```swift +var formatter: NSDataDetector +``` + +```swift +var className: String = NSStringFromClass(MyClass.self) +``` + +```swift +_ = URLRequest.CachePolicy.reloadIgnoringLocalCacheData +``` + +```swift +_ = Notification.Name("com.apple.Music.playerInfo") +``` + +```swift +// +// allowed_types: ["NSData", "NSNumber", "NSURLRequest"] +// + +class SLURLRequest: NSURLRequest { + let data = NSData() + let number: NSNumber +} + +``` + +## Triggering Examples + +```swift +var array = ↓NSArray() +``` + +```swift +var calendar: ↓NSCalendar? = nil +``` + +```swift +_ = ↓NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData +``` + +```swift +_ = ↓NSNotification.Name("com.apple.Music.playerInfo") +``` + +```swift +let keyValuePair: (Int) -> (↓NSString, ↓NSString) = { + let n = "\($0)" as ↓NSString; return (n, n) +} +dictionary = [↓NSString: ↓NSString](uniqueKeysWithValues: + (1...10_000).lazy.map(keyValuePair)) +``` + +```swift +extension Foundation.Notification.Name { + static var reachabilityChanged: Foundation.↓NSNotification.Name { + return Foundation.Notification.Name("org.wordpress.reachability.changed") + } +} +``` \ No newline at end of file diff --git a/docs/description/legacy_random.md b/docs/description/legacy_random.md new file mode 100644 index 0000000..fa3df34 --- /dev/null +++ b/docs/description/legacy_random.md @@ -0,0 +1,54 @@ +# Legacy Random + +Prefer using `type.random(in:)` over legacy functions + +* **Identifier:** `legacy_random` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +Int.random(in: 0..<10) +``` + +```swift +Double.random(in: 8.6...111.34) +``` + +```swift +Float.random(in: 0 ..< 1) +``` + +## Triggering Examples + +```swift +↓arc4random() +``` + +```swift +↓arc4random_uniform(83) +``` + +```swift +↓drand48() +``` \ No newline at end of file diff --git a/docs/description/let_var_whitespace.md b/docs/description/let_var_whitespace.md new file mode 100644 index 0000000..25a78fb --- /dev/null +++ b/docs/description/let_var_whitespace.md @@ -0,0 +1,265 @@ +# Variable Declaration Whitespace + +Variable declarations should be separated from other statements by a blank line + +* **Identifier:** `let_var_whitespace` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class C { +let a = 0 +var x = 1 + +var y = 2 +} +``` + +```swift +class C { +let a = 5 + +var x = 1 +} +``` + +```swift +class C { +var a = 0 +} +``` + +```swift +class C { +let a = 1 + + 2 +let b = 5 +} +``` + +```swift +class C { +var x: Int { + return 0 +} +} +``` + +```swift +class C { +var x: Int { + let a = 0 + + return a +} +} +``` + +```swift +class C { +#if os(macOS) +let a = 0 + +func f() {} +#endif +} +``` + +```swift +class C { +#warning("TODO: remove it") +let a = 0 +#warning("TODO: remove it") +let b = 0 +} +``` + +```swift +class C { +#error("TODO: remove it") +let a = 0 +} +``` + +```swift +class C { +@available(swift 4) +let a = 0 +} +``` + +```swift +class C { +@objc +var s: String = "" +} +``` + +```swift +class C { +@objc +func a() {} +} +``` + +```swift +class C { +var x = 0 +lazy +var y = 0 +} +``` + +```swift +class C { +@available(OSX, introduced: 10.6) +@available(*, deprecated) +var x = 0 +} +``` + +```swift +class C { +// swiftlint:disable superfluous_disable_command +// swiftlint:disable force_cast + +let x = bar as! Bar +} +``` + +```swift +class C { +@available(swift 4) +@UserDefault("param", defaultValue: true) +var isEnabled = true + +@Attribute +func f() {} +} +``` + +```swift +class C { +var x: Int { + let a = 0 + return a +} +} +``` + +```swift +a = 2 +``` + +```swift +a = 2 + +var b = 3 +``` + +```swift +#warning("message") +let a = 2 +``` + +```swift +#if os(macOS) +let a = 2 +#endif +``` + +```swift +f { + let a = 1 + return a +} +``` + +```swift +func f() { + #if os(macOS) + let a = 2 + return a + #else + return 1 + #endif +} +``` + +## Triggering Examples + +```swift +class C { +let a +↓func x() {} +} +``` + +```swift +class C { +var x = 0 +↓@objc func f() {} +} +``` + +```swift +class C { +var x = 0 +↓@objc +func f() {} +} +``` + +```swift +class C { +@objc func f() { +} +↓var x = 0 +} +``` + +```swift +class C { +func f() {} +↓@Wapper +let isNumber = false +@Wapper +var isEnabled = true +↓func g() {} +} +``` + +```swift +class C { +#if os(macOS) +let a = 0 +↓func f() {} +#endif +} +``` + +```swift +let a = 2 +↓b = 1 +``` \ No newline at end of file diff --git a/docs/description/line_length.md b/docs/description/line_length.md new file mode 100644 index 0000000..5c17751 --- /dev/null +++ b/docs/description/line_length.md @@ -0,0 +1,110 @@ +# Line Length + +Lines should not span too many characters. + +* **Identifier:** `line_length` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 120 +
+ error + + 200 +
+ ignores_urls + + false +
+ ignores_function_declarations + + false +
+ ignores_comments + + false +
+ ignores_interpolated_strings + + false +
+ ignores_multiline_strings + + false +
+ excluded_lines_patterns + + [] +
+ +## Non Triggering Examples + +```swift +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +``` + +```swift +#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1) +``` + +```swift +#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg") +``` + +## Triggering Examples + +```swift +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +``` + +```swift +#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1) +``` + +```swift +#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg")#imageLiteral(resourceName: "image.jpg") +``` \ No newline at end of file diff --git a/docs/description/literal_expression_end_indentation.md b/docs/description/literal_expression_end_indentation.md new file mode 100644 index 0000000..d122ac0 --- /dev/null +++ b/docs/description/literal_expression_end_indentation.md @@ -0,0 +1,97 @@ +# Literal Expression End Indentation + +Array and dictionary literal end should have the same indentation as the line that started it + +* **Identifier:** `literal_expression_end_indentation` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[1, 2, 3] +``` + +```swift +[1, + 2 +] +``` + +```swift +[ + 1, + 2 +] +``` + +```swift +[ + 1, + 2] +``` + +```swift + let x = [ + 1, + 2 + ] +``` + +```swift +[key: 2, key2: 3] +``` + +```swift +[key: 1, + key2: 2 +] +``` + +```swift +[ + key: 0, + key2: 20 +] +``` + +## Triggering Examples + +```swift +let x = [ + 1, + 2 + ↓] +``` + +```swift + let x = [ + 1, + 2 +↓] +``` + +```swift +let x = [ + key: value + ↓] +``` \ No newline at end of file diff --git a/docs/description/local_doc_comment.md b/docs/description/local_doc_comment.md new file mode 100644 index 0000000..a744b40 --- /dev/null +++ b/docs/description/local_doc_comment.md @@ -0,0 +1,60 @@ +# Local Doc Comment + +Prefer regular comments over doc comments in local scopes + +* **Identifier:** `local_doc_comment` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func foo() { + // Local scope documentation should use normal comments. + print("foo") +} +``` + +```swift +/// My great property +var myGreatProperty: String! +``` + +```swift +/// Look here for more info: https://github.com. +var myGreatProperty: String! +``` + +```swift +/// Look here for more info: +/// https://github.com. +var myGreatProperty: String! +``` + +## Triggering Examples + +```swift +func foo() { + ↓/// Docstring inside a function declaration + print("foo") +} +``` \ No newline at end of file diff --git a/docs/description/lower_acl_than_parent.md b/docs/description/lower_acl_than_parent.md new file mode 100644 index 0000000..299c9fd --- /dev/null +++ b/docs/description/lower_acl_than_parent.md @@ -0,0 +1,174 @@ +# Lower ACL than Parent + +Ensure declarations have a lower access control level than their enclosing parent + +* **Identifier:** `lower_acl_than_parent` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +public struct Foo { public func bar() {} } +``` + +```swift +internal struct Foo { func bar() {} } +``` + +```swift +struct Foo { func bar() {} } +``` + +```swift +struct Foo { internal func bar() {} } +``` + +```swift +open class Foo { public func bar() {} } +``` + +```swift +open class Foo { open func bar() {} } +``` + +```swift +fileprivate struct Foo { private func bar() {} } +``` + +```swift +private struct Foo { private func bar(id: String) } +``` + +```swift +extension Foo { public func bar() {} } +``` + +```swift +private struct Foo { fileprivate func bar() {} } +``` + +```swift +private func foo(id: String) {} +``` + +```swift +private class Foo { func bar() {} } +``` + +```swift +public extension Foo { struct Bar { public func baz() {} }} +``` + +```swift +public extension Foo { struct Bar { internal func baz() {} }} +``` + +```swift +internal extension Foo { struct Bar { internal func baz() {} }} +``` + +```swift +extension Foo { struct Bar { internal func baz() {} }} +``` + +## Triggering Examples + +```swift +struct Foo { ↓public func bar() {} } +``` + +```swift +enum Foo { ↓public func bar() {} } +``` + +```swift +public class Foo { ↓open func bar() } +``` + +```swift +class Foo { ↓public private(set) var bar: String? } +``` + +```swift +private struct Foo { ↓public func bar() {} } +``` + +```swift +private class Foo { ↓public func bar() {} } +``` + +```swift +private actor Foo { ↓public func bar() {} } +``` + +```swift +fileprivate struct Foo { ↓public func bar() {} } +``` + +```swift +class Foo { ↓public func bar() {} } +``` + +```swift +actor Foo { ↓public func bar() {} } +``` + +```swift +private struct Foo { ↓internal func bar() {} } +``` + +```swift +fileprivate struct Foo { ↓internal func bar() {} } +``` + +```swift +extension Foo { struct Bar { ↓public func baz() {} }} +``` + +```swift +internal extension Foo { struct Bar { ↓public func baz() {} }} +``` + +```swift +private extension Foo { struct Bar { ↓public func baz() {} }} +``` + +```swift +fileprivate extension Foo { struct Bar { ↓public func baz() {} }} +``` + +```swift +private extension Foo { struct Bar { ↓internal func baz() {} }} +``` + +```swift +fileprivate extension Foo { struct Bar { ↓internal func baz() {} }} +``` + +```swift +public extension Foo { struct Bar { struct Baz { ↓public func qux() {} }}} +``` + +```swift +final class Foo { ↓public func bar() {} } +``` \ No newline at end of file diff --git a/docs/description/mark.md b/docs/description/mark.md new file mode 100644 index 0000000..66e9b5b --- /dev/null +++ b/docs/description/mark.md @@ -0,0 +1,208 @@ +# Mark + +MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...' + +* **Identifier:** `mark` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +// MARK: good +``` + +```swift +// MARK: - good +``` + +```swift +// MARK: - +``` + +```swift +// MARK: - +``` + +```swift +// BOOKMARK +``` + +```swift +//BOOKMARK +``` + +```swift +// BOOKMARKS +``` + +```swift +// MARK: This is good. +``` + +```swift +// MARK: - This is good. +``` + +```swift +// MARK: --- This is good. --- +``` + +```swift +// MARK: – This is dash separator +``` + +```swift +// Mark text +``` + +```swift +// MarkdownText.swift +``` + +```swift +// MARK: good +func foo() { + let bar = 0 + // MARK: good +} +``` + +```swift +/* +func test1() { +} +//MARK: mark +func test2() { +} +*/ +``` + +## Triggering Examples + +```swift +↓//MARK: bad +``` + +```swift +↓// MARK:bad +``` + +```swift +↓//MARK:bad +``` + +```swift +↓// MARK: bad +``` + +```swift +↓// MARK: bad +``` + +```swift +↓// MARK: -bad +``` + +```swift +↓// MARK:- bad +``` + +```swift +↓// MARK:-bad +``` + +```swift +↓//MARK: - bad +``` + +```swift +↓//MARK:- bad +``` + +```swift +↓//MARK: -bad +``` + +```swift +↓//MARK:-bad +``` + +```swift +↓//Mark: bad +``` + +```swift +↓// Mark: bad +``` + +```swift +↓// MARK bad +``` + +```swift +↓//MARK bad +``` + +```swift +↓// MARK - bad +``` + +```swift +↓//MARK : bad +``` + +```swift +↓// MARKL: +``` + +```swift +↓// MARKR +``` + +```swift +↓// MARKK - +``` + +```swift +↓/// MARK: +``` + +```swift +↓/// MARK bad +``` + +```swift +// MARK: good +func foo() { + let bar = 0 + ↓//MARK: bad +} +``` + +```swift +↓//MARK:- Top-Level bad mark +↓//MARK:- Another bad mark +struct MarkTest {} +↓// MARK:- Bad mark +extension MarkTest {} +``` \ No newline at end of file diff --git a/docs/description/missing_docs.md b/docs/description/missing_docs.md new file mode 100644 index 0000000..5f24342 --- /dev/null +++ b/docs/description/missing_docs.md @@ -0,0 +1,291 @@ +# Missing Docs + +Declarations should be documented. + +* **Identifier:** `missing_docs` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ warning + + [open, public] +
+ excludes_extensions + + true +
+ excludes_inherited_types + + true +
+ excludes_trivial_init + + false +
+ evaluate_effective_access_control_level + + false +
+ +## Non Triggering Examples + +```swift +/// docs +public class A { +/// docs +public func b() {} +} +// no docs +public class B: A { override public func b() {} } +``` + +```swift +import Foundation +// no docs +public class B: NSObject { +// no docs +override public var description: String { fatalError() } } +``` + +```swift +/// docs +public class A { + var j = 1 + var i: Int { 1 } + func f() {} + deinit {} +} +``` + +```swift +public extension A {} +``` + +```swift +enum E { + case A +} +``` + +```swift +// +// excludes_trivial_init: true +// + +/// docs +public class A { + public init() {} +} + +``` + +```swift +// +// evaluate_effective_access_control_level: true +// + +class C { + public func f() {} +} + +``` + +```swift +public struct S: ~Copyable, P { + public init() {} +} +``` + +## Triggering Examples + +```swift +public ↓func a() {} +``` + +```swift +// regular comment +public ↓func a() {} +``` + +```swift +/* regular comment */ +public ↓func a() {} +``` + +```swift +/// docs +public protocol A { + // no docs + ↓var b: Int { get } +} +/// docs +public struct C: A { + public let b: Int +} +``` + +```swift +/// a doc +public class C { + public static ↓let i = 1 +} +``` + +```swift +public extension A { + public ↓func f() {} + static ↓var i: Int { 1 } + ↓struct S { + func f() {} + } + ↓class C { + func f() {} + } + ↓actor A { + func f() {} + } + ↓enum E { + ↓case a + func f() {} + } +} +``` + +```swift +public extension A { + ↓enum E { + enum Inner { + case a + } + } +} +``` + +```swift +extension E { + public ↓struct S { + public static ↓let i = 1 + } +} +``` + +```swift +extension E { + public ↓func f() {} +} +``` + +```swift +// +// excludes_trivial_init: true +// + +/// docs +public class A { + public ↓init(argument: String) {} +} + +``` + +```swift +// +// excludes_inherited_types: false +// + +public ↓struct C: A { + public ↓let b: Int +} + +``` + +```swift +// +// excludes_extensions: false +// + +public ↓extension A { + public ↓func f() {} +} + +``` + +```swift +public extension E { + ↓var i: Int { + let j = 1 + func f() {} + return j + } +} +``` + +```swift +#if os(macOS) +public ↓func f() {} +#endif +``` + +```swift +public ↓enum E { + ↓case A, B + func f() {} + init(_ i: Int) { self = .A } +} +``` + +```swift +/// a doc +public struct S {} +public extension S { + ↓enum E { + ↓case A + } +} +``` + +```swift +// +// evaluate_effective_access_control_level: false +// + +class C { + public ↓func f() {} +} + +``` + +```swift +public ↓struct S: ~Copyable, ~Escapable { + public ↓init() {} +} +``` \ No newline at end of file diff --git a/docs/description/modifier_order.md b/docs/description/modifier_order.md new file mode 100644 index 0000000..ed81d66 --- /dev/null +++ b/docs/description/modifier_order.md @@ -0,0 +1,293 @@ +# Modifier Order + +Modifier order should be consistent. + +* **Identifier:** `modifier_order` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ preferred_modifier_order + + [override, acl, setterACL, dynamic, mutators, lazy, final, required, convenience, typeMethods, owned] +
+ +## Non Triggering Examples + +```swift +public class Foo { + public required convenience init() {} +} +``` + +```swift +public class Foo { + public static let bar = 42 +} +``` + +```swift +public class Foo { + public static var bar: Int { + return + } +} +``` + +```swift +public class Foo { + public class var bar: Int { + return 42 + } +} +``` + +```swift +public class Bar { + public class var foo: String { + return "foo" + } +} +public class Foo: Bar { + override public final class var foo: String { + return "bar" + } +} +``` + +```swift +open class Bar { + public var foo: Int? { + return 42 + } +} +open class Foo: Bar { + override public var foo: Int? { + return 43 + } +} +``` + +```swift +open class Bar { + open class func foo() -> Int { + return 42 + } +} +class Foo: Bar { + override open class func foo() -> Int { + return 43 + } +} +``` + +```swift +protocol Foo: class {} +class Bar { + public private(set) weak var foo: Foo? +} +``` + +```swift +@objc +public final class Foo: NSObject {} +``` + +```swift +@objcMembers +public final class Foo: NSObject {} +``` + +```swift +@objc +override public private(set) weak var foo: Bar? +``` + +```swift +@objc +public final class Foo: NSObject {} +``` + +```swift +@objc +open final class Foo: NSObject { + open weak var weakBar: NSString? = nil +} +``` + +```swift +public final class Foo {} +``` + +```swift +class Bar { + func bar() {} +} +``` + +```swift +internal class Foo: Bar { + override internal func bar() {} +} +``` + +```swift +public struct Foo { + internal weak var weakBar: NSObject? = nil +} +``` + +```swift +class Foo { + internal lazy var bar: String = "foo" +} +``` + +## Triggering Examples + +```swift +class Foo { + convenience required public init() {} +} +``` + +```swift +public class Foo { + static public let bar = 42 +} +``` + +```swift +public class Foo { + static public var bar: Int { + return 42 + } +} +``` + +```swift +public class Foo { + class public var bar: Int { + return 42 + } +} +``` + +```swift +public class RootFoo { + class public var foo: String { + return "foo" + } +} +public class Foo: RootFoo { + override final class public var foo: String + return "bar" + } +} +``` + +```swift +open class Bar { + public var foo: Int? { + return 42 + } +} +open class Foo: Bar { + public override var foo: Int? { + return 43 + } +} +``` + +```swift +protocol Foo: class {} + class Bar { + private(set) public weak var foo: Foo? +} +``` + +```swift +open class Bar { + open class func foo() -> Int { + return 42 + } +} +class Foo: Bar { + class open override func foo() -> Int { + return 43 + } +} +``` + +```swift +open class Bar { + open class func foo() -> Int { + return 42 + } +} +class Foo: Bar { + open override class func foo() -> Int { + return 43 + } +} +``` + +```swift +@objc +final public class Foo: NSObject {} +``` + +```swift +@objcMembers +final public class Foo: NSObject {} +``` + +```swift +@objc +final open class Foo: NSObject { + weak open var weakBar: NSString? = nil +} +``` + +```swift +final public class Foo {} +``` + +```swift +internal class Foo: Bar { + internal override func bar() {} +} +``` + +```swift +public struct Foo { + weak internal var weakBar: NSObjetc? = nil +} +``` + +```swift +class Foo { + lazy internal var bar: String = "foo" +} +``` \ No newline at end of file diff --git a/docs/description/multiline_arguments.md b/docs/description/multiline_arguments.md new file mode 100644 index 0000000..4ce1766 --- /dev/null +++ b/docs/description/multiline_arguments.md @@ -0,0 +1,179 @@ +# Multiline Arguments + +Arguments should be either on the same line, or one per line + +* **Identifier:** `multiline_arguments` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ first_argument_location + + any_line +
+ only_enforce_after_first_closure_on_first_line + + false +
+ +## Non Triggering Examples + +```swift +foo() +``` + +```swift +foo( +) +``` + +```swift +foo { } +``` + +```swift +foo { + +} +``` + +```swift +foo(0) +``` + +```swift +foo(0, 1) +``` + +```swift +foo(0, 1) { } +``` + +```swift +foo(0, param1: 1) +``` + +```swift +foo(0, param1: 1) { } +``` + +```swift +foo(param1: 1) +``` + +```swift +foo(param1: 1) { } +``` + +```swift +foo(param1: 1, param2: true) { } +``` + +```swift +foo(param1: 1, param2: true, param3: [3]) { } +``` + +```swift +foo(param1: 1, param2: true, param3: [3]) { + bar() +} +``` + +```swift +foo(param1: 1, + param2: true, + param3: [3]) +``` + +```swift +foo( + param1: 1, param2: true, param3: [3] +) +``` + +```swift +foo( + param1: 1, + param2: true, + param3: [3] +) +``` + +```swift +Picker(selection: viewStore.binding(\.$someProperty)) { + ForEach(SomeEnum.allCases, id: \.rawValue) { someCase in + Text(someCase.rawValue) + .tag(someCase) + } +} label: { + EmptyView() +} +``` + +```swift +UIView.animate(withDuration: 1, + delay: 0) { + // sample + print("a") +} completion: { _ in + // sample + print("b") +} +``` + +```swift +UIView.animate(withDuration: 1, delay: 0) { + print("a") +} completion: { _ in + print("b") +} +``` + +## Triggering Examples + +```swift +foo(0, + param1: 1, ↓param2: true, ↓param3: [3]) +``` + +```swift +foo(0, ↓param1: 1, + param2: true, ↓param3: [3]) +``` + +```swift +foo(0, ↓param1: 1, ↓param2: true, + param3: [3]) +``` + +```swift +foo( + 0, ↓param1: 1, + param2: true, ↓param3: [3] +) +``` \ No newline at end of file diff --git a/docs/description/multiline_arguments_brackets.md b/docs/description/multiline_arguments_brackets.md new file mode 100644 index 0000000..ae25874 --- /dev/null +++ b/docs/description/multiline_arguments_brackets.md @@ -0,0 +1,184 @@ +# Multiline Arguments Brackets + +Multiline arguments should have their surrounding brackets in a new line + +* **Identifier:** `multiline_arguments_brackets` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +foo(param1: "Param1", param2: "Param2", param3: "Param3") +``` + +```swift +foo( + param1: "Param1", param2: "Param2", param3: "Param3" +) +``` + +```swift +func foo( + param1: "Param1", + param2: "Param2", + param3: "Param3" +) +``` + +```swift +foo { param1, param2 in + print("hello world") +} +``` + +```swift +foo( + bar( + x: 5, + y: 7 + ) +) +``` + +```swift +AlertViewModel.AlertAction(title: "some title", style: .default) { + AlertManager.shared.presentNextDebugAlert() +} +``` + +```swift +public final class Logger { + public static let shared = Logger(outputs: [ + OSLoggerOutput(), + ErrorLoggerOutput() + ]) +} +``` + +```swift +let errors = try self.download([ + (description: description, priority: priority), +]) +``` + +```swift +return SignalProducer({ observer, _ in + observer.sendCompleted() +}).onMainQueue() +``` + +```swift +SomeType(a: [ + 1, 2, 3 +], b: [1, 2]) +``` + +```swift +SomeType( + a: 1 +) { print("completion") } +``` + +```swift +SomeType( + a: 1 +) { + print("completion") +} +``` + +```swift +SomeType( + a: .init() { print("completion") } +) +``` + +```swift +SomeType( + a: .init() { + print("completion") + } +) +``` + +```swift +SomeType( + a: 1 +) {} onError: {} +``` + +## Triggering Examples + +```swift +foo(↓param1: "Param1", param2: "Param2", + param3: "Param3" +) +``` + +```swift +foo( + param1: "Param1", + param2: "Param2", + param3: "Param3"↓) +``` + +```swift +foo(↓param1: "Param1", + param2: "Param2", + param3: "Param3"↓) +``` + +```swift +foo(↓bar( + x: 5, + y: 7 +) +) +``` + +```swift +foo( + bar( + x: 5, + y: 7 +)↓) +``` + +```swift +SomeOtherType(↓a: [ + 1, 2, 3 + ], + b: "two"↓) +``` + +```swift +SomeOtherType( + a: 1↓) {} +``` + +```swift +SomeOtherType( + a: 1↓) { + print("completion") +} +``` \ No newline at end of file diff --git a/docs/description/multiline_function_chains.md b/docs/description/multiline_function_chains.md new file mode 100644 index 0000000..8c1329c --- /dev/null +++ b/docs/description/multiline_function_chains.md @@ -0,0 +1,125 @@ +# Multiline Function Chains + +Chained function calls should be either on the same line, or one per line + +* **Identifier:** `multiline_function_chains` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let evenSquaresSum = [20, 17, 35, 4].filter { $0 % 2 == 0 }.map { $0 * $0 }.reduce(0, +) +``` + +```swift +let evenSquaresSum = [20, 17, 35, 4] + .filter { $0 % 2 == 0 }.map { $0 * $0 }.reduce(0, +)", +``` + +```swift +let chain = a + .b(1, 2, 3) + .c { blah in + print(blah) + } + .d() +``` + +```swift +let chain = a.b(1, 2, 3) + .c { blah in + print(blah) + } + .d() +``` + +```swift +let chain = a.b(1, 2, 3) + .c { blah in print(blah) } + .d() +``` + +```swift +let chain = a.b(1, 2, 3) + .c(.init( + a: 1, + b, 2, + c, 3)) + .d() +``` + +```swift +self.viewModel.outputs.postContextualNotification + .observeForUI() + .observeValues { + NotificationCenter.default.post( + Notification( + name: .ksr_showNotificationsDialog, + userInfo: [UserInfoKeys.context: PushNotificationDialog.Context.pledge, + UserInfoKeys.viewController: self] + ) + ) + } +``` + +```swift +let remainingIDs = Array(Set(self.currentIDs).subtracting(Set(response.ids))) +``` + +```swift +self.happeningNewsletterOn = self.updateCurrentUser + .map { $0.newsletters.happening }.skipNil().skipRepeats() +``` + +## Triggering Examples + +```swift +let evenSquaresSum = [20, 17, 35, 4] + .filter { $0 % 2 == 0 }↓.map { $0 * $0 } + .reduce(0, +) +``` + +```swift +let evenSquaresSum = a.b(1, 2, 3) + .c { blah in + print(blah) + }↓.d() +``` + +```swift +let evenSquaresSum = a.b(1, 2, 3) + .c(2, 3, 4)↓.d() +``` + +```swift +let evenSquaresSum = a.b(1, 2, 3)↓.c { blah in + print(blah) + } + .d() +``` + +```swift +a.b { +// ““ +}↓.e() +``` \ No newline at end of file diff --git a/docs/description/multiline_literal_brackets.md b/docs/description/multiline_literal_brackets.md new file mode 100644 index 0000000..78ea6a8 --- /dev/null +++ b/docs/description/multiline_literal_brackets.md @@ -0,0 +1,138 @@ +# Multiline Literal Brackets + +Multiline literals should have their surrounding brackets in a new line + +* **Identifier:** `multiline_literal_brackets` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let trio = ["harry", "ronald", "hermione"] +let houseCup = ["gryffindor": 460, "hufflepuff": 370, "ravenclaw": 410, "slytherin": 450] +``` + +```swift +let trio = [ + "harry", + "ronald", + "hermione" +] +let houseCup = [ + "gryffindor": 460, + "hufflepuff": 370, + "ravenclaw": 410, + "slytherin": 450 +] +``` + +```swift +let trio = [ + "harry", "ronald", "hermione" +] +let houseCup = [ + "gryffindor": 460, "hufflepuff": 370, + "ravenclaw": 410, "slytherin": 450 +] +``` + +```swift +_ = [ + 1, + 2, + 3, + 4, + 5, 6, + 7, 8, 9 +] +``` + +## Triggering Examples + +```swift +let trio = [↓"harry", + "ronald", + "hermione" +] +``` + +```swift +let houseCup = [↓"gryffindor": 460, "hufflepuff": 370, + "ravenclaw": 410, "slytherin": 450 +] +``` + +```swift +let houseCup = [↓"gryffindor": 460, + "hufflepuff": 370, + "ravenclaw": 410, + "slytherin": 450↓] +``` + +```swift +let trio = [ + "harry", + "ronald", + "hermione"↓] +``` + +```swift +let houseCup = [ + "gryffindor": 460, "hufflepuff": 370, + "ravenclaw": 410, "slytherin": 450↓] +``` + +```swift +class Hogwarts { + let houseCup = [ + "gryffindor": 460, "hufflepuff": 370, + "ravenclaw": 410, "slytherin": 450↓] +} +``` + +```swift +_ = [ + 1, + 2, + 3, + 4, + 5, 6, + 7, 8, 9↓] +``` + +```swift +_ = [↓1, 2, 3, + 4, 5, 6, + 7, 8, 9 +] +``` + +```swift +class Hogwarts { + let houseCup = [ + "gryffindor": 460, "hufflepuff": 370, + "ravenclaw": 410, "slytherin": slytherinPoints.filter { + $0.isValid + }.sum()↓] +} +``` \ No newline at end of file diff --git a/docs/description/multiline_parameters.md b/docs/description/multiline_parameters.md new file mode 100644 index 0000000..b58113c --- /dev/null +++ b/docs/description/multiline_parameters.md @@ -0,0 +1,628 @@ +# Multiline Parameters + +Functions and methods parameters should be either on the same line, or one per line + +* **Identifier:** `multiline_parameters` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ allows_single_line + + true +
+ +## Non Triggering Examples + +```swift +func foo() { } +``` + +```swift +func foo(param1: Int) { } +``` + +```swift +func foo(param1: Int, param2: Bool) { } +``` + +```swift +func foo(param1: Int, param2: Bool, param3: [String]) { } +``` + +```swift +func foo(param1: Int, + param2: Bool, + param3: [String]) { } +``` + +```swift +func foo(_ param1: Int, param2: Int, param3: Int) -> (Int) -> Int { + return { x in x + param1 + param2 + param3 } +} +``` + +```swift +static func foo() { } +``` + +```swift +static func foo(param1: Int) { } +``` + +```swift +static func foo(param1: Int, param2: Bool) { } +``` + +```swift +static func foo(param1: Int, param2: Bool, param3: [String]) { } +``` + +```swift +static func foo(param1: Int, + param2: Bool, + param3: [String]) { } +``` + +```swift +protocol Foo { + func foo() { } +} +``` + +```swift +protocol Foo { + func foo(param1: Int) { } +} +``` + +```swift +protocol Foo { + func foo(param1: Int, param2: Bool) { } +} +``` + +```swift +protocol Foo { + func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +protocol Foo { + func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +protocol Foo { + static func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +protocol Foo { + static func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +protocol Foo { + class func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +protocol Foo { + class func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +enum Foo { + func foo() { } +} +``` + +```swift +enum Foo { + func foo(param1: Int) { } +} +``` + +```swift +enum Foo { + func foo(param1: Int, param2: Bool) { } +} +``` + +```swift +enum Foo { + func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +enum Foo { + func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +enum Foo { + static func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +enum Foo { + static func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +struct Foo { + func foo() { } +} +``` + +```swift +struct Foo { + func foo(param1: Int) { } +} +``` + +```swift +struct Foo { + func foo(param1: Int, param2: Bool) { } +} +``` + +```swift +struct Foo { + func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +struct Foo { + func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +struct Foo { + static func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +struct Foo { + static func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +class Foo { + func foo() { } +} +``` + +```swift +class Foo { + func foo(param1: Int) { } +} +``` + +```swift +class Foo { + func foo(param1: Int, param2: Bool) { } +} +``` + +```swift +class Foo { + func foo(param1: Int, param2: Bool, param3: [String]) { } + } +``` + +```swift +class Foo { + func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, param2: Bool, param3: [String]) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: Bool, + param3: @escaping (Int, Int) -> Void = { _, _ in }) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: Bool, + param3: @escaping (Int) -> Void = { _ in }) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: Bool, + param3: @escaping ((Int) -> Void)? = nil) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: Bool, + param3: @escaping ((Int) -> Void)? = { _ in }) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: @escaping ((Int) -> Void)? = { _ in }, + param3: Bool) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: @escaping ((Int) -> Void)? = { _ in }, + param3: @escaping (Int, Int) -> Void = { _, _ in }) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: Bool, + param3: @escaping (Int) -> Void = { (x: Int) in }) { } +} +``` + +```swift +class Foo { + class func foo(param1: Int, + param2: Bool, + param3: @escaping (Int, (Int) -> Void) -> Void = { (x: Int, f: (Int) -> Void) in }) { } +} +``` + +```swift +class Foo { + init(param1: Int, + param2: Bool, + param3: @escaping ((Int) -> Void)? = { _ in }) { } +} +``` + +```swift +// +// allows_single_line: false +// + +func foo() { } + +``` + +```swift +// +// allows_single_line: false +// + +func foo(param1: Int) { } + +``` + +```swift +// +// allows_single_line: false +// + +protocol Foo { + func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} + +``` + +```swift +// +// allows_single_line: false +// + +protocol Foo { + func foo( + param1: Int + ) { } +} + +``` + +```swift +// +// allows_single_line: false +// + +protocol Foo { + func foo( + param1: Int, + param2: Bool, + param3: [String] + ) { } +} + +``` + +```swift +// +// max_number_of_single_line_parameters: 3 +// + +func foo(param1: Int, param2: Bool, param3: [String]) { } + +``` + +```swift +// +// max_number_of_single_line_parameters: 3 +// + +func foo(param1: Int, + param2: Bool, + param3: [String]) { } + +``` + +## Triggering Examples + +```swift +func ↓foo(_ param1: Int, + param2: Int, param3: Int) -> (Int) -> Int { + return { x in x + param1 + param2 + param3 } +} +``` + +```swift +protocol Foo { + func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +protocol Foo { + func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +protocol Foo { + static func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +protocol Foo { + static func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +protocol Foo { + class func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +protocol Foo { + class func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +enum Foo { + func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +enum Foo { + func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +enum Foo { + static func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +enum Foo { + static func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +struct Foo { + func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +struct Foo { + func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +struct Foo { + static func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +struct Foo { + static func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +class Foo { + func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +class Foo { + func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +class Foo { + class func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } +} +``` + +```swift +class Foo { + class func ↓foo(param1: Int, param2: Bool, + param3: [String]) { } +} +``` + +```swift +class Foo { + class func ↓foo(param1: Int, + param2: Bool, param3: @escaping (Int, Int) -> Void = { _, _ in }) { } +} +``` + +```swift +class Foo { + class func ↓foo(param1: Int, + param2: Bool, param3: @escaping (Int) -> Void = { (x: Int) in }) { } +} +``` + +```swift +class Foo { + ↓init(param1: Int, param2: Bool, + param3: @escaping ((Int) -> Void)? = { _ in }) { } +} +``` + +```swift +// +// allows_single_line: false +// + +func ↓foo(param1: Int, param2: Bool) { } + +``` + +```swift +// +// allows_single_line: false +// + +func ↓foo(param1: Int, param2: Bool, param3: [String]) { } + +``` + +```swift +// +// max_number_of_single_line_parameters: 2 +// + +func ↓foo(param1: Int, param2: Bool, param3: [String]) { } + +``` + +```swift +// +// max_number_of_single_line_parameters: 3 +// + +func ↓foo(param1: Int, + param2: Bool, param3: [String]) { } + +``` \ No newline at end of file diff --git a/docs/description/multiline_parameters_brackets.md b/docs/description/multiline_parameters_brackets.md new file mode 100644 index 0000000..c351945 --- /dev/null +++ b/docs/description/multiline_parameters_brackets.md @@ -0,0 +1,118 @@ +# Multiline Parameters Brackets + +Multiline parameters should have their surrounding brackets in a new line + +* **Identifier:** `multiline_parameters_brackets` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func foo(param1: String, param2: String, param3: String) +``` + +```swift +func foo( + param1: String, param2: String, param3: String +) +``` + +```swift +func foo( + param1: String, + param2: String, + param3: String +) +``` + +```swift +class SomeType { + func foo(param1: String, param2: String, param3: String) +} +``` + +```swift +class SomeType { + func foo( + param1: String, param2: String, param3: String + ) +} +``` + +```swift +class SomeType { + func foo( + param1: String, + param2: String, + param3: String + ) +} +``` + +```swift +func foo(param1: T, param2: String, param3: String) -> T { /* some code */ } +``` + +```swift + func foo(a: [Int] = [ + 1 + ]) +``` + +## Triggering Examples + +```swift +func foo(↓param1: String, param2: String, + param3: String +) +``` + +```swift +func foo( + param1: String, + param2: String, + param3: String↓) +``` + +```swift +class SomeType { + func foo(↓param1: String, param2: String, + param3: String + ) +} +``` + +```swift +class SomeType { + func foo( + param1: String, + param2: String, + param3: String↓) +} +``` + +```swift +func foo(↓param1: T, param2: String, + param3: String +) -> T +``` \ No newline at end of file diff --git a/docs/description/multiple_closures_with_trailing_closure.md b/docs/description/multiple_closures_with_trailing_closure.md new file mode 100644 index 0000000..f2e9fb7 --- /dev/null +++ b/docs/description/multiple_closures_with_trailing_closure.md @@ -0,0 +1,82 @@ +# Multiple Closures with Trailing Closure + +Trailing closure syntax should not be used when passing more than one closure argument + +* **Identifier:** `multiple_closures_with_trailing_closure` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +foo.map { $0 + 1 } +``` + +```swift +foo.reduce(0) { $0 + $1 } +``` + +```swift +if let foo = bar.map({ $0 + 1 }) { + +} +``` + +```swift +foo.something(param1: { $0 }, param2: { $0 + 1 }) +``` + +```swift +UIView.animate(withDuration: 1.0) { + someView.alpha = 0.0 +} +``` + +```swift +foo.method { print(0) } arg2: { print(1) } +``` + +```swift +foo.methodWithParenArgs((0, 1), arg2: (0, 1, 2)) { $0 } arg4: { $0 } +``` + +## Triggering Examples + +```swift +foo.something(param1: { $0 }) ↓{ $0 + 1 } +``` + +```swift +UIView.animate(withDuration: 1.0, animations: { + someView.alpha = 0.0 +}) ↓{ _ in + someView.removeFromSuperview() +} +``` + +```swift +foo.multipleTrailing(arg1: { $0 }) { $0 } arg3: { $0 } +``` + +```swift +foo.methodWithParenArgs(param1: { $0 }, param2: (0, 1), (0, 1)) { $0 } +``` \ No newline at end of file diff --git a/docs/description/nesting.md b/docs/description/nesting.md new file mode 100644 index 0000000..b43584b --- /dev/null +++ b/docs/description/nesting.md @@ -0,0 +1,1448 @@ +# Nesting + +Types should be nested at most 1 level deep, and functions should be nested at most 2 levels deep. + +* **Identifier:** `nesting` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ type_level + + + + + + + + + + + +
KeyValue
+ warning + + 1 +
+
+ function_level + + + + + + + + + + + +
KeyValue
+ warning + + 2 +
+
+ check_nesting_in_closures_and_statements + + true +
+ always_allow_one_type_in_functions + + false +
+ ignore_typealiases_and_associatedtypes + + false +
+ +## Non Triggering Examples + +```swift +actor Example_0 { + actor Example_1 {} +} +``` + +```swift +var example: Int { + actor Example_0 { + actor Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + actor Example_0 { + actor Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + actor Example_1 {} +} +``` + +```swift +class Example_0 { + class Example_1 {} +} +``` + +```swift +var example: Int { + class Example_0 { + class Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + class Example_0 { + class Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + class Example_1 {} +} +``` + +```swift +struct Example_0 { + struct Example_1 {} +} +``` + +```swift +var example: Int { + struct Example_0 { + struct Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + struct Example_0 { + struct Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + struct Example_1 {} +} +``` + +```swift +enum Example_0 { + enum Example_1 {} +} +``` + +```swift +var example: Int { + enum Example_0 { + enum Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + enum Example_0 { + enum Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + enum Example_1 {} +} +``` + +```swift +func f_0() { + func f_1() { + func f_2() {} + } +} +``` + +```swift +var example: Int { + func f_0() { + func f_1() { + func f_2() {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + func f_0() { + func f_1() { + func f_2() {} + } + } + } +} +``` + +```swift +extension Example_0 { + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +switch example { +case .exampleCase: + actor Example_0 { + actor Example_1 {} + } +default: + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + actor Example_0 { + actor Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +exampleFunc(closure: { + actor Example_0 { + actor Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +}) +``` + +```swift +switch example { +case .exampleCase: + class Example_0 { + class Example_1 {} + } +default: + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + class Example_0 { + class Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +exampleFunc(closure: { + class Example_0 { + class Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +}) +``` + +```swift +switch example { +case .exampleCase: + struct Example_0 { + struct Example_1 {} + } +default: + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + struct Example_0 { + struct Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +exampleFunc(closure: { + struct Example_0 { + struct Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +}) +``` + +```swift +switch example { +case .exampleCase: + enum Example_0 { + enum Example_1 {} + } +default: + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + enum Example_0 { + enum Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +} +``` + +```swift +exampleFunc(closure: { + enum Example_0 { + enum Example_1 {} + } + func f_0() { + func f_1() { + func f_2() {} + } + } +}) +``` + +```swift +actor Example_0 { + protocol Example_1 {} +} +``` + +```swift +var example: Int { + actor Example_0 { + protocol Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + actor Example_0 { + protocol Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + protocol Example_1 {} +} +``` + +```swift +class Example_0 { + protocol Example_1 {} +} +``` + +```swift +var example: Int { + class Example_0 { + protocol Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + class Example_0 { + protocol Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + protocol Example_1 {} +} +``` + +```swift +struct Example_0 { + protocol Example_1 {} +} +``` + +```swift +var example: Int { + struct Example_0 { + protocol Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + struct Example_0 { + protocol Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + protocol Example_1 {} +} +``` + +```swift +enum Example_0 { + protocol Example_1 {} +} +``` + +```swift +var example: Int { + enum Example_0 { + protocol Example_1 {} + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + enum Example_0 { + protocol Example_1 {} + } + } +} +``` + +```swift +extension Example_0 { + protocol Example_1 {} +} +``` + +```swift +actor Example_0 { + func f_0() { + actor Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + } +} +``` + +```swift +actor Example_0 { + func f_0() { + switch example { + case .exampleCase: + actor Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + default: + exampleFunc(closure: { + actor Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + }) + } + } +} +``` + +```swift +class Example_0 { + func f_0() { + class Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + } +} +``` + +```swift +class Example_0 { + func f_0() { + switch example { + case .exampleCase: + class Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + default: + exampleFunc(closure: { + class Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + }) + } + } +} +``` + +```swift +struct Example_0 { + func f_0() { + struct Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + } +} +``` + +```swift +struct Example_0 { + func f_0() { + switch example { + case .exampleCase: + struct Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + default: + exampleFunc(closure: { + struct Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + }) + } + } +} +``` + +```swift +enum Example_0 { + func f_0() { + enum Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + } +} +``` + +```swift +enum Example_0 { + func f_0() { + switch example { + case .exampleCase: + enum Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + default: + exampleFunc(closure: { + enum Example_1 { + func f_1() { + func f_2() {} + } + } + protocol P {} + }) + } + } +} +``` + +## Triggering Examples + +```swift +actor Example_0 { + actor Example_1 { + ↓actor Example_2 {} + } +} +``` + +```swift +var example: Int { + actor Example_0 { + actor Example_1 { + ↓actor Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + actor Example_0 { + actor Example_1 { + ↓actor Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + actor Example_1 { + ↓actor Example_2 {} + } +} +``` + +```swift +class Example_0 { + class Example_1 { + ↓class Example_2 {} + } +} +``` + +```swift +var example: Int { + class Example_0 { + class Example_1 { + ↓class Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + class Example_0 { + class Example_1 { + ↓class Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + class Example_1 { + ↓class Example_2 {} + } +} +``` + +```swift +struct Example_0 { + struct Example_1 { + ↓struct Example_2 {} + } +} +``` + +```swift +var example: Int { + struct Example_0 { + struct Example_1 { + ↓struct Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + struct Example_0 { + struct Example_1 { + ↓struct Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + struct Example_1 { + ↓struct Example_2 {} + } +} +``` + +```swift +enum Example_0 { + enum Example_1 { + ↓enum Example_2 {} + } +} +``` + +```swift +var example: Int { + enum Example_0 { + enum Example_1 { + ↓enum Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + enum Example_0 { + enum Example_1 { + ↓enum Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + enum Example_1 { + ↓enum Example_2 {} + } +} +``` + +```swift +func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } +} +``` + +```swift +var example: Int { + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } + } +} +``` + +```swift +extension Example_0 { + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +switch example { +case .exampleCase: + actor Example_0 { + actor Example_1 { + ↓actor Example_2 {} + } + } +default: + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + actor Example_0 { + actor Example_1 { + ↓actor Example_2 {} + } + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +exampleFunc(closure: { + actor Example_0 { + actor Example_1 {} + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +}) +``` + +```swift +switch example { +case .exampleCase: + class Example_0 { + class Example_1 { + ↓class Example_2 {} + } + } +default: + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + class Example_0 { + class Example_1 { + ↓class Example_2 {} + } + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +exampleFunc(closure: { + class Example_0 { + class Example_1 {} + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +}) +``` + +```swift +switch example { +case .exampleCase: + struct Example_0 { + struct Example_1 { + ↓struct Example_2 {} + } + } +default: + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + struct Example_0 { + struct Example_1 { + ↓struct Example_2 {} + } + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +exampleFunc(closure: { + struct Example_0 { + struct Example_1 {} + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +}) +``` + +```swift +switch example { +case .exampleCase: + enum Example_0 { + enum Example_1 { + ↓enum Example_2 {} + } + } +default: + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +var exampleClosure: () -> Void = { + enum Example_0 { + enum Example_1 { + ↓enum Example_2 {} + } + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +} +``` + +```swift +exampleFunc(closure: { + enum Example_0 { + enum Example_1 {} + } + func f_0() { + func f_1() { + func f_2() { + ↓func f_3() {} + } + } + } +}) +``` + +```swift +actor Example_0 { + actor Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +var example: Int { + actor Example_0 { + actor Example_1 { + ↓protocol Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + actor Example_0 { + actor Example_1 { + ↓protocol Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + actor Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +class Example_0 { + class Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +var example: Int { + class Example_0 { + class Example_1 { + ↓protocol Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + class Example_0 { + class Example_1 { + ↓protocol Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + class Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +struct Example_0 { + struct Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +var example: Int { + struct Example_0 { + struct Example_1 { + ↓protocol Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + struct Example_0 { + struct Example_1 { + ↓protocol Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + struct Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +enum Example_0 { + enum Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +var example: Int { + enum Example_0 { + enum Example_1 { + ↓protocol Example_2 {} + } + } + return 5 +} +``` + +```swift +var example: Int = 5 { + didSet { + enum Example_0 { + enum Example_1 { + ↓protocol Example_2 {} + } + } + } +} +``` + +```swift +extension Example_0 { + enum Example_1 { + ↓protocol Example_2 {} + } +} +``` + +```swift +actor Example_0 { + func f_0() { + actor Example_1 { + func f_1() { + func f_2() { + ↓actor Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + } +} +``` + +```swift +actor Example_0 { + func f_0() { + switch example { + case .exampleCase: + actor Example_1 { + func f_1() { + func f_2() { + ↓actor Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + default: + exampleFunc(closure: { + actor Example_1 { + func f_1() { + func f_2() { + ↓actor Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + }) + } + } +} +``` + +```swift +class Example_0 { + func f_0() { + class Example_1 { + func f_1() { + func f_2() { + ↓class Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + } +} +``` + +```swift +class Example_0 { + func f_0() { + switch example { + case .exampleCase: + class Example_1 { + func f_1() { + func f_2() { + ↓class Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + default: + exampleFunc(closure: { + class Example_1 { + func f_1() { + func f_2() { + ↓class Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + }) + } + } +} +``` + +```swift +struct Example_0 { + func f_0() { + struct Example_1 { + func f_1() { + func f_2() { + ↓struct Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + } +} +``` + +```swift +struct Example_0 { + func f_0() { + switch example { + case .exampleCase: + struct Example_1 { + func f_1() { + func f_2() { + ↓struct Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + default: + exampleFunc(closure: { + struct Example_1 { + func f_1() { + func f_2() { + ↓struct Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + }) + } + } +} +``` + +```swift +enum Example_0 { + func f_0() { + enum Example_1 { + func f_1() { + func f_2() { + ↓enum Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + } +} +``` + +```swift +enum Example_0 { + func f_0() { + switch example { + case .exampleCase: + enum Example_1 { + func f_1() { + func f_2() { + ↓enum Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + default: + exampleFunc(closure: { + enum Example_1 { + func f_1() { + func f_2() { + ↓enum Example_2 {} + ↓func f_3() {} + ↓protocol P {} + } + } + } + }) + } + } +} +``` \ No newline at end of file diff --git a/docs/description/nimble_operator.md b/docs/description/nimble_operator.md new file mode 100644 index 0000000..0738821 --- /dev/null +++ b/docs/description/nimble_operator.md @@ -0,0 +1,146 @@ +# Nimble Operator + +Prefer Nimble operator overloads over free matcher functions + +* **Identifier:** `nimble_operator` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +expect(seagull.squawk) != "Hi!" +``` + +```swift +expect("Hi!") == "Hi!" +``` + +```swift +expect(10) > 2 +``` + +```swift +expect(10) >= 10 +``` + +```swift +expect(10) < 11 +``` + +```swift +expect(10) <= 10 +``` + +```swift +expect(x) === x +``` + +```swift +expect(10) == 10 +``` + +```swift +expect(success) == true +``` + +```swift +expect(value) == nil +``` + +```swift +expect(value) != nil +``` + +```swift +expect(object.asyncFunction()).toEventually(equal(1)) +``` + +```swift +expect(actual).to(haveCount(expected)) +``` + +```swift +foo.method { + expect(value).to(equal(expectedValue), description: "Failed") + return Bar(value: ()) +} +``` + +## Triggering Examples + +```swift +↓expect(seagull.squawk).toNot(equal("Hi")) +``` + +```swift +↓expect(12).toNot(equal(10)) +``` + +```swift +↓expect(10).to(equal(10)) +``` + +```swift +↓expect(10, line: 1).to(equal(10)) +``` + +```swift +↓expect(10).to(beGreaterThan(8)) +``` + +```swift +↓expect(10).to(beGreaterThanOrEqualTo(10)) +``` + +```swift +↓expect(10).to(beLessThan(11)) +``` + +```swift +↓expect(10).to(beLessThanOrEqualTo(10)) +``` + +```swift +↓expect(x).to(beIdenticalTo(x)) +``` + +```swift +↓expect(success).to(beTrue()) +``` + +```swift +↓expect(success).to(beFalse()) +``` + +```swift +↓expect(value).to(beNil()) +``` + +```swift +↓expect(value).toNot(beNil()) +``` + +```swift +expect(10) > 2 + ↓expect(10).to(beGreaterThan(2)) +``` \ No newline at end of file diff --git a/docs/description/no_empty_block.md b/docs/description/no_empty_block.md new file mode 100644 index 0000000..414e625 --- /dev/null +++ b/docs/description/no_empty_block.md @@ -0,0 +1,199 @@ +# No Empty Block + +Code blocks should contain at least one statement or comment + +* **Identifier:** `no_empty_block` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ disabled_block_types + + [] +
+ +## Non Triggering Examples + +```swift +func f() { + /* do something */ +} + +var flag = true { + willSet { /* do something */ } +} +``` + +```swift +class Apple { + init() { /* do something */ } + + deinit { /* do something */ } +} +``` + +```swift +for _ in 0..<10 { /* do something */ } + +do { + /* do something */ +} catch { + /* do something */ +} + +func f() { + defer { + /* do something */ + } + print("other code") +} + +if flag { + /* do something */ +} else { + /* do something */ +} + +repeat { /* do something */ } while (flag) + +while i < 10 { /* do something */ } +``` + +```swift +// +// disabled_block_types: [function_bodies] +// + +func f() {} + +var flag = true { + willSet {} +} + +``` + +```swift +// +// disabled_block_types: [initializer_bodies] +// + +class Apple { + init() {} + + deinit {} +} + +``` + +```swift +// +// disabled_block_types: [statement_blocks] +// + +for _ in 0..<10 {} + +do { +} catch { +} + +func f() { + defer {} + print("other code") +} + +if flag { +} else { +} + +repeat {} while (flag) + +while i < 10 {} + +``` + +```swift +f { _ in /* comment */ } +f { _ in // comment +} +f { _ in + // comment +} +``` + +```swift +// +// disabled_block_types: [closure_blocks] +// + +f {} +{}() + +``` + +## Triggering Examples + +```swift +func f() ↓{} + +var flag = true { + willSet ↓{} +} +``` + +```swift +class Apple { + init() ↓{} + + deinit ↓{} +} +``` + +```swift +for _ in 0..<10 ↓{} + +do ↓{ +} catch ↓{ +} + +func f() { + defer ↓{} + print("other code") +} + +if flag ↓{ +} else ↓{ +} + +repeat ↓{} while (flag) + +while i < 10 ↓{} +``` + +```swift +f ↓{} +``` + +```swift +Button ↓{} label: ↓{} +``` \ No newline at end of file diff --git a/docs/description/no_extension_access_modifier.md b/docs/description/no_extension_access_modifier.md new file mode 100644 index 0000000..8bc5ba2 --- /dev/null +++ b/docs/description/no_extension_access_modifier.md @@ -0,0 +1,61 @@ +# No Extension Access Modifier + +Prefer not to use extension access modifiers + +* **Identifier:** `no_extension_access_modifier` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +extension String {} +``` + +```swift + + + extension String {} +``` + +## Triggering Examples + +```swift +↓private extension String {} +``` + +```swift +↓public + extension String {} +``` + +```swift +↓open extension String {} +``` + +```swift +↓internal extension String {} +``` + +```swift +↓fileprivate extension String {} +``` \ No newline at end of file diff --git a/docs/description/no_fallthrough_only.md b/docs/description/no_fallthrough_only.md new file mode 100644 index 0000000..109fcfa --- /dev/null +++ b/docs/description/no_fallthrough_only.md @@ -0,0 +1,198 @@ +# No Fallthrough only + +Fallthroughs can only be used if the `case` contains at least one other statement + +* **Identifier:** `no_fallthrough_only` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +switch myvar { +case 1: + var a = 1 + fallthrough +case 2: + var a = 2 +} +``` + +```swift +switch myvar { +case "a": + var one = 1 + var two = 2 + fallthrough +case "b": /* comment */ + var three = 3 +} +``` + +```swift +switch myvar { +case 1: + let one = 1 +case 2: + // comment + var two = 2 +} +``` + +```swift +switch myvar { +case MyFunc(x: [1, 2, YourFunc(a: 23)], y: 2): + var three = 3 + fallthrough +default: + var three = 4 +} +``` + +```swift +switch myvar { +case .alpha: + var one = 1 +case .beta: + var three = 3 + fallthrough +default: + var four = 4 +} +``` + +```swift +let aPoint = (1, -1) +switch aPoint { +case let (x, y) where x == y: + let A = "A" +case let (x, y) where x == -y: + let B = "B" + fallthrough +default: + let C = "C" +} +``` + +```swift +switch myvar { +case MyFun(with: { $1 }): + let one = 1 + fallthrough +case "abc": + let two = 2 +} +``` + +```swift +switch enumInstance { +case .caseA: + print("it's a") +case .caseB: + fallthrough +@unknown default: + print("it's not a") +} +``` + +## Triggering Examples + +```swift +switch myvar { +case 1: + ↓fallthrough +case 2: + var a = 1 +} +``` + +```swift +switch myvar { +case 1: + var a = 2 +case 2: + ↓fallthrough +case 3: + var a = 3 +} +``` + +```swift +switch myvar { +case 1: // comment + ↓fallthrough +} +``` + +```swift +switch myvar { +case 1: /* multi + line + comment */ + ↓fallthrough +case 2: + var a = 2 +} +``` + +```swift +switch myvar { +case MyFunc(x: [1, 2, YourFunc(a: 23)], y: 2): + ↓fallthrough +default: + var three = 4 +} +``` + +```swift +switch myvar { +case .alpha: + var one = 1 +case .beta: + ↓fallthrough +case .gamma: + var three = 3 +default: + var four = 4 +} +``` + +```swift +let aPoint = (1, -1) +switch aPoint { +case let (x, y) where x == y: + let A = "A" +case let (x, y) where x == -y: + ↓fallthrough +default: + let B = "B" +} +``` + +```swift +switch myvar { +case MyFun(with: { $1 }): + ↓fallthrough +case "abc": + let two = 2 +} +``` \ No newline at end of file diff --git a/docs/description/no_grouping_extension.md b/docs/description/no_grouping_extension.md new file mode 100644 index 0000000..199956a --- /dev/null +++ b/docs/description/no_grouping_extension.md @@ -0,0 +1,65 @@ +# No Grouping Extension + +Extensions shouldn't be used to group code within the same source file + +* **Identifier:** `no_grouping_extension` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +protocol Food {} +extension Food {} +``` + +```swift +class Apples {} +extension Oranges {} +``` + +```swift +class Box {} +extension Box where T: Vegetable {} +``` + +## Triggering Examples + +```swift +enum Fruit {} +↓extension Fruit {} +``` + +```swift +↓extension Tea: Error {} +struct Tea {} +``` + +```swift +class Ham { class Spam {}} +↓extension Ham.Spam {} +``` + +```swift +extension External { struct Gotcha {}} +↓extension External.Gotcha {} +``` \ No newline at end of file diff --git a/docs/description/no_magic_numbers.md b/docs/description/no_magic_numbers.md new file mode 100644 index 0000000..41d4f88 --- /dev/null +++ b/docs/description/no_magic_numbers.md @@ -0,0 +1,307 @@ +# No Magic Numbers + +Magic numbers should be replaced by named constants + +* **Identifier:** `no_magic_numbers` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ test_parent_classes + + ["QuickSpec", "XCTestCase"] +
+ allowed_numbers + + [0.0, 1.0, 100.0] +
+ +## Non Triggering Examples + +```swift +var foo = 123 +``` + +```swift +static let bar: Double = 0.123 +``` + +```swift +let a = b + 1.0 +``` + +```swift +array[0] + array[1] +``` + +```swift +let foo = 1_000.000_01 +``` + +```swift +// array[1337] +``` + +```swift +baz("9999") +``` + +```swift +func foo() { + let x: Int = 2 + let y = 3 + let vector = [x, y, -1] +} +``` + +```swift +class A { + var foo: Double = 132 + static let bar: Double = 0.98 +} +``` + +```swift +@available(iOS 13, *) +func version() { + if #available(iOS 13, OSX 10.10, *) { + return + } +} +``` + +```swift +enum Example: Int { + case positive = 2 + case negative = -2 +} +``` + +```swift +class FooTests: XCTestCase { + let array: [Int] = [] + let bar = array[42] +} +``` + +```swift +class FooTests: XCTestCase { + class Bar { + let array: [Int] = [] + let bar = array[42] + } +} +``` + +```swift +class MyTest: XCTestCase {} +extension MyTest { + let a = Int(3) +} +``` + +```swift +extension MyTest { + let a = Int(3) +} +class MyTest: XCTestCase {} +``` + +```swift +let foo = 1 << 2 +``` + +```swift +let foo = 1 >> 2 +``` + +```swift +let foo = 2 >> 2 +``` + +```swift +let foo = 2 << 2 +``` + +```swift +let a = b / 100.0 +``` + +```swift +let range = 2 ..< 12 +``` + +```swift +let range = ...12 +``` + +```swift +let range = 12... +``` + +```swift +let (lowerBound, upperBound) = (400, 599) +``` + +```swift +let a = (5, 10) +``` + +```swift +let notFound = (statusCode: 404, description: "Not Found", isError: true) +``` + +```swift +#Preview { ContentView(value: 5) } +``` + +```swift +@Test func f() { let _ = 2 + 2 } +``` + +```swift +@Suite struct Test { + @Test func f() { + func g() { let _ = 2 + 2 } + let _ = 2 + 2 + } +} +``` + +```swift +@Suite actor Test { + private var a: Int { 2 } + @Test func f() { let _ = 2 + a } +} +``` + +```swift +class Test { // @Suite implicitly + private var a: Int { 2 } + @Test func f() { let _ = 2 + a } +} +``` + +```swift +#if compiler(<6.0) && compiler(>4.0) +let a = 1 +#elseif compiler(<3.0) +let a = 2 +#endif +``` + +```swift +let myColor: UIColor = UIColor(red: 0.6, green: 1.0, blue: 0.2, alpha: 0.52) +``` + +```swift +let colorLiteral = #colorLiteral(red: 0.7019607843, green: 0.7019607843, blue: 0.7019607843, alpha: 1) +``` + +## Triggering Examples + +```swift +foo(↓321) +``` + +```swift +bar(↓1_000.005_01) +``` + +```swift +array[↓42] +``` + +```swift +let box = array[↓12 + ↓14] +``` + +```swift +let a = b + ↓2.0 +``` + +```swift +let range = 2 ... ↓12 + 1 +``` + +```swift +let range = ↓2*↓6... +``` + +```swift +let slice = array[↓2...↓4] +``` + +```swift +for i in ↓3 ..< ↓8 {} +``` + +```swift +let n: Int = Int(r * ↓255) << ↓16 | Int(g * ↓255) << ↓8 +``` + +```swift +Color.primary.opacity(isAnimate ? ↓0.1 : ↓1.5) +``` + +```swift + class MyTest: XCTestCase {} + extension NSObject { + let a = Int(↓3) + } +``` + +```swift +if (fileSize > ↓1000000) { + return +} +``` + +```swift +let imageHeight = (width - ↓24) +``` + +```swift +return (↓5, ↓10, ↓15) +``` + +```swift +#ExampleMacro { + ContentView(value: ↓5) +} +``` + +```swift +#if compiler(<6.0) && compiler(>4.0) +f(↓6.0) +#elseif compiler(<3.0) +f(↓3.0) +#else +f(↓4.0) +#endif +``` \ No newline at end of file diff --git a/docs/description/no_space_in_method_call.md b/docs/description/no_space_in_method_call.md new file mode 100644 index 0000000..d9ec334 --- /dev/null +++ b/docs/description/no_space_in_method_call.md @@ -0,0 +1,94 @@ +# No Space in Method Call + +Don't add a space between the method name and the parentheses + +* **Identifier:** `no_space_in_method_call` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +foo() +``` + +```swift +object.foo() +``` + +```swift +object.foo(1) +``` + +```swift +object.foo(value: 1) +``` + +```swift +object.foo { print($0 } +``` + +```swift +list.sorted { $0.0 < $1.0 }.map { $0.value } +``` + +```swift +self.init(rgb: (Int) (colorInt)) +``` + +```swift +Button { + print("Button tapped") +} label: { + Text("Button") +} +``` + +## Triggering Examples + +```swift +foo↓ () +``` + +```swift +object.foo↓ () +``` + +```swift +object.foo↓ (1) +``` + +```swift +object.foo↓ (value: 1) +``` + +```swift +object.foo↓ () {} +``` + +```swift +object.foo↓ () +``` + +```swift +object.foo↓ (value: 1) { x in print(x) } +``` \ No newline at end of file diff --git a/docs/description/non_optional_string_data_conversion.md b/docs/description/non_optional_string_data_conversion.md new file mode 100644 index 0000000..6e3302d --- /dev/null +++ b/docs/description/non_optional_string_data_conversion.md @@ -0,0 +1,38 @@ +# Non-optional String -> Data Conversion + +Prefer non-optional `Data(_:)` initializer when converting `String` to `Data` + +* **Identifier:** `non_optional_string_data_conversion` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +Data("foo".utf8) +``` + +## Triggering Examples + +```swift +"foo".data(using: .utf8) +``` \ No newline at end of file diff --git a/docs/description/non_overridable_class_declaration.md b/docs/description/non_overridable_class_declaration.md new file mode 100644 index 0000000..b22f5ea --- /dev/null +++ b/docs/description/non_overridable_class_declaration.md @@ -0,0 +1,106 @@ +# Class Declaration in Final Class + +Class methods and properties in final classes should themselves be final, just as if the declarations +are private. In both cases, they cannot be overridden. Using `final class` or `static` makes this explicit. + +* **Identifier:** `non_overridable_class_declaration` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ final_class_modifier + + final class +
+ +## Non Triggering Examples + +```swift +final class C { + final class var b: Bool { true } + final class func f() {} +} +``` + +```swift +class C { + final class var b: Bool { true } + final class func f() {} +} +``` + +```swift +class C { + class var b: Bool { true } + class func f() {} +} +``` + +```swift +class C { + static var b: Bool { true } + static func f() {} +} +``` + +```swift +final class C { + static var b: Bool { true } + static func f() {} +} +``` + +```swift +final class C { + class D { + class var b: Bool { true } + class func f() {} + } +} +``` + +## Triggering Examples + +```swift +final class C { + ↓class var b: Bool { true } + ↓class func f() {} +} +``` + +```swift +class C { + final class D { + ↓class var b: Bool { true } + ↓class func f() {} + } +} +``` + +```swift +class C { + private ↓class var b: Bool { true } + private ↓class func f() {} +} +``` \ No newline at end of file diff --git a/docs/description/notification_center_detachment.md b/docs/description/notification_center_detachment.md new file mode 100644 index 0000000..70b6a24 --- /dev/null +++ b/docs/description/notification_center_detachment.md @@ -0,0 +1,54 @@ +# Notification Center Detachment + +An object should only remove itself as an observer in `deinit` + +* **Identifier:** `notification_center_detachment` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Foo { + deinit { + NotificationCenter.default.removeObserver(self) + } +} +``` + +```swift +class Foo { + func bar() { + NotificationCenter.default.removeObserver(otherObject) + } +} +``` + +## Triggering Examples + +```swift +class Foo { + func bar() { + ↓NotificationCenter.default.removeObserver(self) + } +} +``` \ No newline at end of file diff --git a/docs/description/ns_number_init_as_function_reference.md b/docs/description/ns_number_init_as_function_reference.md new file mode 100644 index 0000000..7da1b66 --- /dev/null +++ b/docs/description/ns_number_init_as_function_reference.md @@ -0,0 +1,58 @@ +# NSNumber Init as Function Reference + +Passing `NSNumber.init` or `NSDecimalNumber.init` as a function reference is dangerous as it can cause the wrong initializer to be used, causing crashes; use `.init(value:)` instead + +* **Identifier:** `ns_number_init_as_function_reference` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[0, 0.2].map(NSNumber.init(value:)) +``` + +```swift +let value = NSNumber.init(value: 0.0) +``` + +```swift +[0, 0.2].map { NSNumber(value: $0) } +``` + +```swift +[0, 0.2].map(NSDecimalNumber.init(value:)) +``` + +```swift +[0, 0.2].map { NSDecimalNumber(value: $0) } +``` + +## Triggering Examples + +```swift +[0, 0.2].map(↓NSNumber.init) +``` + +```swift +[0, 0.2].map(↓NSDecimalNumber.init) +``` \ No newline at end of file diff --git a/docs/description/nslocalizedstring_key.md b/docs/description/nslocalizedstring_key.md new file mode 100644 index 0000000..e3c5188 --- /dev/null +++ b/docs/description/nslocalizedstring_key.md @@ -0,0 +1,69 @@ +# NSLocalizedString Key + +Static strings should be used as key/comment in NSLocalizedString in order for genstrings to work + +* **Identifier:** `nslocalizedstring_key` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +NSLocalizedString("key", comment: "") +``` + +```swift +NSLocalizedString("key" + "2", comment: "") +``` + +```swift +NSLocalizedString("key", comment: "comment") +``` + +```swift +NSLocalizedString("This is a multi-" + + "line string", comment: "") +``` + +```swift +let format = NSLocalizedString("%@, %@.", comment: "Accessibility label for a post in the post list." + +" The parameters are the title, and date respectively." + +" For example, "Let it Go, 1 hour ago."") +``` + +## Triggering Examples + +```swift +NSLocalizedString(↓method(), comment: "") +``` + +```swift +NSLocalizedString(↓"key_\(param)", comment: "") +``` + +```swift +NSLocalizedString("key", comment: ↓"comment with \(param)") +``` + +```swift +NSLocalizedString(↓"key_\(param)", comment: ↓method()) +``` \ No newline at end of file diff --git a/docs/description/nslocalizedstring_require_bundle.md b/docs/description/nslocalizedstring_require_bundle.md new file mode 100644 index 0000000..c25b2ea --- /dev/null +++ b/docs/description/nslocalizedstring_require_bundle.md @@ -0,0 +1,63 @@ +# NSLocalizedString Require Bundle + +Calls to NSLocalizedString should specify the bundle which contains the strings file + +* **Identifier:** `nslocalizedstring_require_bundle` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +NSLocalizedString("someKey", bundle: .main, comment: "test") +``` + +```swift +NSLocalizedString("someKey", tableName: "a", + bundle: Bundle(for: A.self), + comment: "test") +``` + +```swift +NSLocalizedString("someKey", tableName: "xyz", + bundle: someBundle, value: "test" + comment: "test") +``` + +```swift +arbitraryFunctionCall("something") +``` + +## Triggering Examples + +```swift +↓NSLocalizedString("someKey", comment: "test") +``` + +```swift +↓NSLocalizedString("someKey", tableName: "a", comment: "test") +``` + +```swift +↓NSLocalizedString("someKey", tableName: "xyz", + value: "test", comment: "test") +``` \ No newline at end of file diff --git a/docs/description/nsobject_prefer_isequal.md b/docs/description/nsobject_prefer_isequal.md new file mode 100644 index 0000000..ac70c2c --- /dev/null +++ b/docs/description/nsobject_prefer_isequal.md @@ -0,0 +1,126 @@ +# NSObject Prefer isEqual + +NSObject subclasses should implement isEqual instead of == + +* **Identifier:** `nsobject_prefer_isequal` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class AClass: NSObject { +} +``` + +```swift +@objc class AClass: SomeNSObjectSubclass { +} +``` + +```swift +class AClass: Equatable { + static func ==(lhs: AClass, rhs: AClass) -> Bool { + return true + } +``` + +```swift +class AClass: NSObject { + override func isEqual(_ object: Any?) -> Bool { + return true + } +} +``` + +```swift +@objc class AClass: SomeNSObjectSubclass { + override func isEqual(_ object: Any?) -> Bool { + return false + } +} +``` + +```swift +class AClass: NSObject { + static func ==(lhs: AClass, rhs: BClass) -> Bool { + return true + } +} +``` + +```swift +struct AStruct: Equatable { + static func ==(lhs: AStruct, rhs: AStruct) -> Bool { + return false + } +} +``` + +```swift +enum AnEnum: Equatable { + static func ==(lhs: AnEnum, rhs: AnEnum) -> Bool { + return true + } +} +``` + +## Triggering Examples + +```swift +class AClass: NSObject { + ↓static func ==(lhs: AClass, rhs: AClass) -> Bool { + return false + } +} +``` + +```swift +@objc class AClass: SomeOtherNSObjectSubclass { + ↓static func ==(lhs: AClass, rhs: AClass) -> Bool { + return true + } +} +``` + +```swift +class AClass: NSObject, Equatable { + ↓static func ==(lhs: AClass, rhs: AClass) -> Bool { + return false + } +} +``` + +```swift +class AClass: NSObject { + override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? AClass else { + return false + } + return true + } + + ↓static func ==(lhs: AClass, rhs: AClass) -> Bool { + return false + } +} +``` \ No newline at end of file diff --git a/docs/description/number_separator.md b/docs/description/number_separator.md new file mode 100644 index 0000000..eb33f0b --- /dev/null +++ b/docs/description/number_separator.md @@ -0,0 +1,445 @@ +# Number Separator + +Underscores should be used as thousand separator in large numbers with a configurable number of digits. In other words, there should be an underscore after every 3 digits in the integral as well as the fractional part of a number. + +* **Identifier:** `number_separator` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ minimum_length + + 0 +
+ exclude_ranges + + [] +
+ +## Non Triggering Examples + +```swift +let foo = -100 +``` + +```swift +let foo = -1_000 +``` + +```swift +let foo = -1_000_000 +``` + +```swift +let foo = -1.0001 +``` + +```swift +let foo = -1_000_000.0000001 +``` + +```swift +let binary = -0b10000 +``` + +```swift +let binary = -0b1000_0001 +``` + +```swift +let hex = -0xA +``` + +```swift +let hex = -0xAA_BB +``` + +```swift +let octal = -0o21 +``` + +```swift +let octal = -0o21_1 +``` + +```swift +let exp = -1_000_000.000000e2 +``` + +```swift +let foo: Double = -(200) +``` + +```swift +let foo: Double = -(200 / 447.214) +``` + +```swift +let foo = -6.2832e-6 +``` + +```swift +let foo = +100 +``` + +```swift +let foo = +1_000 +``` + +```swift +let foo = +1_000_000 +``` + +```swift +let foo = +1.0001 +``` + +```swift +let foo = +1_000_000.0000001 +``` + +```swift +let binary = +0b10000 +``` + +```swift +let binary = +0b1000_0001 +``` + +```swift +let hex = +0xA +``` + +```swift +let hex = +0xAA_BB +``` + +```swift +let octal = +0o21 +``` + +```swift +let octal = +0o21_1 +``` + +```swift +let exp = +1_000_000.000000e2 +``` + +```swift +let foo: Double = +(200) +``` + +```swift +let foo: Double = +(200 / 447.214) +``` + +```swift +let foo = +6.2832e-6 +``` + +```swift +let foo = 100 +``` + +```swift +let foo = 1_000 +``` + +```swift +let foo = 1_000_000 +``` + +```swift +let foo = 1.0001 +``` + +```swift +let foo = 1_000_000.0000001 +``` + +```swift +let binary = 0b10000 +``` + +```swift +let binary = 0b1000_0001 +``` + +```swift +let hex = 0xA +``` + +```swift +let hex = 0xAA_BB +``` + +```swift +let octal = 0o21 +``` + +```swift +let octal = 0o21_1 +``` + +```swift +let exp = 1_000_000.000000e2 +``` + +```swift +let foo: Double = (200) +``` + +```swift +let foo: Double = (200 / 447.214) +``` + +```swift +let foo = 6.2832e-6 +``` + +## Triggering Examples + +```swift +let foo = -↓10_0 +``` + +```swift +let foo = -↓1000 +``` + +```swift +let foo = -↓1000e2 +``` + +```swift +let foo = -↓1000E2 +``` + +```swift +let foo = -↓1__000 +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = -↓1.0001 + +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = -↓1_000_000.000000_1 + +``` + +```swift +let foo = -↓1000000.000000_1 +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = -↓6.2832e-6 + +``` + +```swift +let foo = +↓10_0 +``` + +```swift +let foo = +↓1000 +``` + +```swift +let foo = +↓1000e2 +``` + +```swift +let foo = +↓1000E2 +``` + +```swift +let foo = +↓1__000 +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = +↓1.0001 + +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = +↓1_000_000.000000_1 + +``` + +```swift +let foo = +↓1000000.000000_1 +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = +↓6.2832e-6 + +``` + +```swift +let foo = ↓10_0 +``` + +```swift +let foo = ↓1000 +``` + +```swift +let foo = ↓1000e2 +``` + +```swift +let foo = ↓1000E2 +``` + +```swift +let foo = ↓1__000 +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = ↓1.0001 + +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = ↓1_000_000.000000_1 + +``` + +```swift +let foo = ↓1000000.000000_1 +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo = ↓6.2832e-6 + +``` + +```swift +let foo: Double = -(↓100000) +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo: Double = -(↓10.000000_1) + +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo: Double = -(↓123456 / ↓447.214214) + +``` + +```swift +let foo: Double = +(↓100000) +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo: Double = +(↓10.000000_1) + +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo: Double = +(↓123456 / ↓447.214214) + +``` + +```swift +let foo: Double = (↓100000) +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo: Double = (↓10.000000_1) + +``` + +```swift +// +// minimum_fraction_length: 3 +// + +let foo: Double = (↓123456 / ↓447.214214) + +``` \ No newline at end of file diff --git a/docs/description/object_literal.md b/docs/description/object_literal.md new file mode 100644 index 0000000..8de1c6d --- /dev/null +++ b/docs/description/object_literal.md @@ -0,0 +1,142 @@ +# Object Literal + +Prefer object literals over image and color inits + +* **Identifier:** `object_literal` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ image_literal + + true +
+ color_literal + + true +
+ +## Non Triggering Examples + +```swift +let image = #imageLiteral(resourceName: "image.jpg") +``` + +```swift +let color = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1) +``` + +```swift +let image = UIImage(named: aVariable) +``` + +```swift +let image = UIImage(named: "interpolated \(variable)") +``` + +```swift +let color = UIColor(red: value, green: value, blue: value, alpha: 1) +``` + +```swift +let image = NSImage(named: aVariable) +``` + +```swift +let image = NSImage(named: "interpolated \(variable)") +``` + +```swift +let color = NSColor(red: value, green: value, blue: value, alpha: 1) +``` + +## Triggering Examples + +```swift +let image = ↓UIImage(named: "foo") +``` + +```swift +let color = ↓UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) +``` + +```swift +let color = ↓UIColor(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) +``` + +```swift +let color = ↓UIColor(white: 0.5, alpha: 1) +``` + +```swift +let image = ↓NSImage(named: "foo") +``` + +```swift +let color = ↓NSColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) +``` + +```swift +let color = ↓NSColor(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) +``` + +```swift +let color = ↓NSColor(white: 0.5, alpha: 1) +``` + +```swift +let image = ↓UIImage.init(named: "foo") +``` + +```swift +let color = ↓UIColor.init(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) +``` + +```swift +let color = ↓UIColor.init(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) +``` + +```swift +let color = ↓UIColor.init(white: 0.5, alpha: 1) +``` + +```swift +let image = ↓NSImage.init(named: "foo") +``` + +```swift +let color = ↓NSColor.init(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) +``` + +```swift +let color = ↓NSColor.init(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) +``` + +```swift +let color = ↓NSColor.init(white: 0.5, alpha: 1) +``` \ No newline at end of file diff --git a/docs/description/one_declaration_per_file.md b/docs/description/one_declaration_per_file.md new file mode 100644 index 0000000..cdc9734 --- /dev/null +++ b/docs/description/one_declaration_per_file.md @@ -0,0 +1,60 @@ +# One Declaration per File + +Only a single declaration is allowed in a file + +* **Identifier:** `one_declaration_per_file` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +actor Foo {} +``` + +```swift +class Foo {} +extension Foo {} +``` + +```swift +struct S { + struct N {} +} +``` + +## Triggering Examples + +```swift +class Foo {} +↓class Bar {} +``` + +```swift +protocol Foo {} +↓enum Bar {} +``` + +```swift +struct Foo {} +↓struct Bar {} +``` \ No newline at end of file diff --git a/docs/description/opening_brace.md b/docs/description/opening_brace.md new file mode 100644 index 0000000..46e6a8e --- /dev/null +++ b/docs/description/opening_brace.md @@ -0,0 +1,394 @@ +# Opening Brace Spacing + +The correct positioning of braces that introduce a block of code or member list is highly controversial. No matter which style is preferred, consistency is key. Apart from different tastes, the positioning of braces can also have a significant impact on the readability of the code, especially for visually impaired developers. This rule ensures that braces are preceded by a single space and on the same line as the declaration. Comments between the declaration and the opening brace are respected. Check out the `contrasted_opening_brace` rule for a different style. + +* **Identifier:** `opening_brace` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ ignore_multiline_type_headers + + false +
+ ignore_multiline_statement_conditions + + false +
+ ignore_multiline_function_signatures + + false +
+ allow_multiline_func + + false +
+ +## Non Triggering Examples + +```swift +func abc() { +} +``` + +```swift +[].map() { $0 } +``` + +```swift +[].map({ }) +``` + +```swift +if let a = b { } +``` + +```swift +while a == b { } +``` + +```swift +guard let a = b else { } +``` + +```swift +struct Rule {} +``` + +```swift +struct Parent { + struct Child { + let foo: Int + } +} +``` + +```swift +func f(rect: CGRect) { + { + let centre = CGPoint(x: rect.midX, y: rect.midY) + print(centre) + }() +} +``` + +```swift +func f(rect: CGRect) -> () -> Void { + { + let centre = CGPoint(x: rect.midX, y: rect.midY) + print(centre) + } +} +``` + +```swift +func f() -> () -> Void { + {} +} +``` + +```swift +class Rule: + NSObject { + var a: String { + return "" + } +} +``` + +```swift +self.foo( + ( + "String parameter", + { "Do something here" } + ) +) +``` + +```swift +let pattern = #/(\{(?\w+)\})/# +``` + +```swift +if c {} +else {} +``` + +```swift + if c /* comment */ { + return + } +``` + +## Triggering Examples + +```swift +func abc()↓{ +} +``` + +```swift +func abc() + ↓{ } +``` + +```swift +func abc(a: A, + b: B) +↓{ +``` + +```swift +[].map()↓{ $0 } +``` + +```swift +struct OldContentView: View { + @State private var showOptions = false + + var body: some View { + Button(action: { + self.showOptions.toggle() + })↓{ + Image(systemName: "gear") + } + } +} +``` + +```swift +struct OldContentView: View { + @State private var showOptions = false + + var body: some View { + Button(action: { + self.showOptions.toggle() + }) + ↓{ + Image(systemName: "gear") + } + } +} +``` + +```swift +struct OldContentView: View { + @State private var showOptions = false + + var body: some View { + Button { + self.showOptions.toggle() + } label:↓{ + Image(systemName: "gear") + } + } +} +``` + +```swift +if let a = b↓{ } +``` + +```swift +while a == b↓{ } +``` + +```swift +guard let a = b else↓{ } +``` + +```swift +if + let a = b, + let c = d + where a == c↓{ } +``` + +```swift +while + let a = b, + let c = d + where a == c↓{ } +``` + +```swift +guard + let a = b, + let c = d + where a == c else↓{ } +``` + +```swift +struct Rule↓{} +``` + +```swift +struct Rule +↓{ +} +``` + +```swift +struct Rule + + ↓{ +} +``` + +```swift +struct Parent { + struct Child + ↓{ + let foo: Int + } +} +``` + +```swift +switch a↓{} +``` + +```swift +if + let a = b, + let c = d, + a == c +↓{ } +``` + +```swift +while + let a = b, + let c = d, + a == c +↓{ } +``` + +```swift +guard + let a = b, + let c = d, + a == c else +↓{ } +``` + +```swift +class Rule↓{} + +``` + +```swift +actor Rule↓{} + +``` + +```swift +enum Rule↓{} + +``` + +```swift +protocol Rule↓{} + +``` + +```swift +extension Rule↓{} + +``` + +```swift +class Rule { + var a: String↓{ + return "" + } +} +``` + +```swift +class Rule { + var a: String { + willSet↓{ + + } + didSet ↓{ + + } + } +} +``` + +```swift +precedencegroup Group↓{ + assignment: true +} +``` + +```swift +if + "test".isEmpty +↓{ + // code here +} +``` + +```swift +func fooFun() { + let foo: String? = "foo" + let bar: String? = "bar" + + if + let foo = foo, + let bar = bar + ↓{ + print(foo + bar) + } +} +``` + +```swift +if + let a = ["A", "B"].first, + let b = ["B"].first +↓{ + print(a) +} +``` + +```swift +if c ↓{} +else /* comment */ ↓{} +``` \ No newline at end of file diff --git a/docs/description/operator_usage_whitespace.md b/docs/description/operator_usage_whitespace.md new file mode 100644 index 0000000..5821d83 --- /dev/null +++ b/docs/description/operator_usage_whitespace.md @@ -0,0 +1,312 @@ +# Operator Usage Whitespace + +Operators should be surrounded by a single whitespace when they are being used + +* **Identifier:** `operator_usage_whitespace` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ lines_look_around + + 2 +
+ skip_aligned_constants + + true +
+ allowed_no_space_operators + + ["...", "..<"] +
+ +## Non Triggering Examples + +```swift +let foo = 1 + 2 +``` + +```swift +let foo = 1 > 2 +``` + +```swift +let foo = !false +``` + +```swift +let foo: Int? +``` + +```swift +let foo: Array +``` + +```swift +let model = CustomView, NSAttributedString>() +``` + +```swift +let foo: [String] +``` + +```swift +let foo = 1 + + 2 +``` + +```swift +let range = 1...3 +``` + +```swift +let range = 1 ... 3 +``` + +```swift +let range = 1..<3 +``` + +```swift +#if swift(>=3.0) + foo() +#endif +``` + +```swift +array.removeAtIndex(-200) +``` + +```swift +let name = "image-1" +``` + +```swift +button.setImage(#imageLiteral(resourceName: "image-1"), for: .normal) +``` + +```swift +let doubleValue = -9e-11 +``` + +```swift +let foo = GenericType<(UIViewController) -> Void>() +``` + +```swift +let foo = Foo, Baz>() +``` + +```swift +let foo = SignalProducer, Error>([ self.signal, next ]).flatten(.concat) +``` + +```swift +"let foo = 1" +``` + +```swift +enum Enum { +case hello = 1 +case hello2 = 1 +} +``` + +```swift +let something = Something() +``` + +```swift +return path.flatMap { path in + return compileCommands[path] ?? + compileCommands[path.path(relativeTo: FileManager.default.currentDirectoryPath)] +} +``` + +```swift +internal static func == (lhs: Vertex, rhs: Vertex) -> Bool { + return lhs.filePath == rhs.filePath + && lhs.originalRemoteString == rhs.originalRemoteString + && lhs.rootDirectory == rhs.rootDirectory +} +``` + +```swift +internal static func == (lhs: Vertex, rhs: Vertex) -> Bool { + return lhs.filePath == rhs.filePath && + lhs.originalRemoteString == rhs.originalRemoteString && + lhs.rootDirectory == rhs.rootDirectory +} +``` + +```swift +private static let pattern = + "\\S\(mainPatternGroups)" + // Regexp will match if expression not begin with comma + "|" + // or + "\(mainPatternGroups)" // Regexp will match if expression begins with comma +``` + +```swift +private static let pattern = + "\\S\(mainPatternGroups)" + // Regexp will match if expression not begin with comma + "|" + // or + "\(mainPatternGroups)" // Regexp will match if expression begins with comma +``` + +```swift +typealias Foo = Bar +``` + +```swift +protocol A { + associatedtype B = C +} +``` + +```swift +tabbedViewController.title = nil +``` + +## Triggering Examples + +```swift +let foo = 1↓+2 +``` + +```swift +let foo = 1↓ + 2 +``` + +```swift +let foo = 1↓ + 2 +``` + +```swift +let foo = 1↓ + 2 +``` + +```swift +let foo↓=1↓+2 +``` + +```swift +let foo↓=1 + 2 +``` + +```swift +let foo↓=bar +``` + +```swift +let range = 1↓ ..< 3 +``` + +```swift +let foo = bar↓ ?? 0 +``` + +```swift +let foo = bar↓ != 0 +``` + +```swift +let foo = bar↓ !== bar2 +``` + +```swift +let v8 = Int8(1)↓ << 6 +``` + +```swift +let v8 = 1↓ << (6) +``` + +```swift +let v8 = 1↓ << (6) + let foo = 1 > 2 +``` + +```swift +let foo↓ = [1] +``` + +```swift +let foo↓ = "1" +``` + +```swift +let foo↓ = "1" +``` + +```swift +enum Enum { +case one↓ = 1 +case two = 1 +} +``` + +```swift +enum Enum { +case one = 1 +case two↓ = 1 +} +``` + +```swift +enum Enum { +case one↓ = 1 +case two↓ = 1 +} +``` + +```swift +typealias Foo↓ = Bar +``` + +```swift +protocol A { + associatedtype B↓ = C +} +``` + +```swift +tabbedViewController.title↓ = nil +``` + +```swift +let foo = bar ? 0↓:1 +``` + +```swift +let foo = bar↓ ? 0 : 1 +``` \ No newline at end of file diff --git a/docs/description/operator_whitespace.md b/docs/description/operator_whitespace.md new file mode 100644 index 0000000..0a8c68b --- /dev/null +++ b/docs/description/operator_whitespace.md @@ -0,0 +1,66 @@ +# Operator Function Whitespace + +Operators should be surrounded by a single whitespace when defining them + +* **Identifier:** `operator_whitespace` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func <| (lhs: Int, rhs: Int) -> Int {} +``` + +```swift +func <|< (lhs: A, rhs: A) -> A {} +``` + +```swift +func abc(lhs: Int, rhs: Int) -> Int {} +``` + +## Triggering Examples + +```swift +↓func <|(lhs: Int, rhs: Int) -> Int {} +``` + +```swift +↓func <|<(lhs: A, rhs: A) -> A {} +``` + +```swift +↓func <| (lhs: Int, rhs: Int) -> Int {} +``` + +```swift +↓func <|< (lhs: A, rhs: A) -> A {} +``` + +```swift +↓func <| (lhs: Int, rhs: Int) -> Int {} +``` + +```swift +↓func <|< (lhs: A, rhs: A) -> A {} +``` \ No newline at end of file diff --git a/docs/description/optional_data_string_conversion.md b/docs/description/optional_data_string_conversion.md new file mode 100644 index 0000000..609361d --- /dev/null +++ b/docs/description/optional_data_string_conversion.md @@ -0,0 +1,54 @@ +# Optional Data -> String Conversion + +Prefer failable `String(bytes:encoding:)` initializer when converting `Data` to `String` + +* **Identifier:** `optional_data_string_conversion` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +String(data: data, encoding: .utf8) +``` + +```swift +String(bytes: data, encoding: .utf8) +``` + +```swift +String(UTF8.self) +``` + +```swift +String(a, b, c, UTF8.self) +``` + +```swift +String(decoding: data, encoding: UTF8.self) +``` + +## Triggering Examples + +```swift +String(decoding: data, as: UTF8.self) +``` \ No newline at end of file diff --git a/docs/description/optional_enum_case_matching.md b/docs/description/optional_enum_case_matching.md new file mode 100644 index 0000000..1094f02 --- /dev/null +++ b/docs/description/optional_enum_case_matching.md @@ -0,0 +1,98 @@ +# Optional Enum Case Match + +Matching an enum case against an optional enum without '?' is supported on Swift 5.1 and above + +* **Identifier:** `optional_enum_case_matching` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.1.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +switch foo { + case .bar: break + case .baz: break + default: break +} +``` + +```swift +switch foo { + case (.bar, .baz): break + case (.bar, _): break + case (_, .baz): break + default: break +} +``` + +```swift +switch (x, y) { +case (.c, _?): + break +case (.c, nil): + break +case (_, _): + break +} +``` + +## Triggering Examples + +```swift +switch foo { + case .bar↓?: break + case .baz: break + default: break +} +``` + +```swift +switch foo { + case Foo.bar↓?: break + case .baz: break + default: break +} +``` + +```swift +switch foo { + case .bar↓?, .baz↓?: break + default: break +} +``` + +```swift +switch foo { + case .bar↓? where x > 1: break + case .baz: break + default: break +} +``` + +```swift +switch foo { + case (.bar↓?, .baz↓?): break + case (.bar↓?, _): break + case (_, .bar↓?): break + default: break +} +``` \ No newline at end of file diff --git a/docs/description/orphaned_doc_comment.md b/docs/description/orphaned_doc_comment.md new file mode 100644 index 0000000..74a446d --- /dev/null +++ b/docs/description/orphaned_doc_comment.md @@ -0,0 +1,92 @@ +# Orphaned Doc Comment + +A doc comment should be attached to a declaration + +* **Identifier:** `orphaned_doc_comment` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +/// My great property +var myGreatProperty: String! +``` + +```swift +////////////////////////////////////// +// +// Copyright header. +// +////////////////////////////////////// +``` + +```swift +/// Look here for more info: https://github.com. +var myGreatProperty: String! +``` + +```swift +/// Look here for more info: +/// https://github.com. +var myGreatProperty: String! +``` + +## Triggering Examples + +```swift +↓/// My great property +// Not a doc string +var myGreatProperty: String! +``` + +```swift +↓/// Look here for more info: https://github.com. +// Not a doc string +var myGreatProperty: String! +``` + +```swift +↓/// Look here for more info: https://github.com. + + +// Not a doc string +var myGreatProperty: String! +``` + +```swift +↓/// Look here for more info: https://github.com. +// Not a doc string +↓/// My great property +// Not a doc string +var myGreatProperty: String! +``` + +```swift +extension Nested { + ↓/// + /// Look here for more info: https://github.com. + + // Not a doc string + var myGreatProperty: String! +} +``` \ No newline at end of file diff --git a/docs/description/overridden_super_call.md b/docs/description/overridden_super_call.md new file mode 100644 index 0000000..f5ba339 --- /dev/null +++ b/docs/description/overridden_super_call.md @@ -0,0 +1,114 @@ +# Overridden Method Calls Super + +Some overridden methods should always call super. + +* **Identifier:** `overridden_super_call` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ excluded + + [] +
+ included + + ["*"] +
+ +## Non Triggering Examples + +```swift +class VC: UIViewController { + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + } +} +``` + +```swift +class VC: UIViewController { + override func viewWillAppear(_ animated: Bool) { + self.method1() + super.viewWillAppear(animated) + self.method2() + } +} +``` + +```swift +class VC: UIViewController { + override func loadView() { + } +} +``` + +```swift +class Some { + func viewWillAppear(_ animated: Bool) { + } +} +``` + +```swift +class VC: UIViewController { + override func viewDidLoad() { + defer { + super.viewDidLoad() + } + } +} +``` + +## Triggering Examples + +```swift +class VC: UIViewController { + override func viewWillAppear(_ animated: Bool) {↓ + //Not calling to super + self.method() + } +} +``` + +```swift +class VC: UIViewController { + override func viewWillAppear(_ animated: Bool) {↓ + super.viewWillAppear(animated) + //Other code + super.viewWillAppear(animated) + } +} +``` + +```swift +class VC: UIViewController { + override func didReceiveMemoryWarning() {↓ + } +} +``` \ No newline at end of file diff --git a/docs/description/override_in_extension.md b/docs/description/override_in_extension.md new file mode 100644 index 0000000..2568250 --- /dev/null +++ b/docs/description/override_in_extension.md @@ -0,0 +1,76 @@ +# Override in Extension + +Extensions shouldn't override declarations + +* **Identifier:** `override_in_extension` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +extension Person { + var age: Int { return 42 } +} +``` + +```swift +extension Person { + func celebrateBirthday() {} +} +``` + +```swift +class Employee: Person { + override func celebrateBirthday() {} +} +``` + +```swift +class Foo: NSObject {} +extension Foo { + override var description: String { return "" } +} +``` + +```swift +struct Foo { + class Bar: NSObject {} +} +extension Foo.Bar { + override var description: String { return "" } +} +``` + +## Triggering Examples + +```swift +extension Person { + override ↓var age: Int { return 42 } +} +``` + +```swift +extension Person { + override ↓func celebrateBirthday() {} +} +``` \ No newline at end of file diff --git a/docs/description/pattern_matching_keywords.md b/docs/description/pattern_matching_keywords.md new file mode 100644 index 0000000..bad8f32 --- /dev/null +++ b/docs/description/pattern_matching_keywords.md @@ -0,0 +1,168 @@ +# Pattern Matching Keywords + +Combine multiple pattern matching bindings by moving keywords out of tuples + +* **Identifier:** `pattern_matching_keywords` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +switch foo { + default: break +} +``` + +```swift +switch foo { + case 1: break +} +``` + +```swift +switch foo { + case bar: break +} +``` + +```swift +switch foo { + case let (x, y): break +} +``` + +```swift +switch foo { + case .foo(let x): break +} +``` + +```swift +switch foo { + case let .foo(x, y): break +} +``` + +```swift +switch foo { + case .foo(let x), .bar(let x): break +} +``` + +```swift +switch foo { + case .foo(let x, var y): break +} +``` + +```swift +switch foo { + case var (x, y): break +} +``` + +```swift +switch foo { + case .foo(var x): break +} +``` + +```swift +switch foo { + case var .foo(x, y): break +} +``` + +```swift +switch foo { + case (y, let x, z): break +} +``` + +## Triggering Examples + +```swift +switch foo { + case (↓let x, ↓let y): break +} +``` + +```swift +switch foo { + case (↓let x, ↓let y, .foo): break +} +``` + +```swift +switch foo { + case (↓let x, ↓let y, _): break +} +``` + +```swift +switch foo { + case (↓let x, ↓let y, f()): break +} +``` + +```swift +switch foo { + case (↓let x, ↓let y, s.f()): break +} +``` + +```swift +switch foo { + case (↓let x, ↓let y, s.t): break +} +``` + +```swift +switch foo { + case .foo(↓let x, ↓let y): break +} +``` + +```swift +switch foo { + case (.yamlParsing(↓let x), .yamlParsing(↓let y)): break +} +``` + +```swift +switch foo { + case (↓var x, ↓var y): break +} +``` + +```swift +switch foo { + case .foo(↓var x, ↓var y): break +} +``` + +```swift +switch foo { + case (.yamlParsing(↓var x), .yamlParsing(↓var y)): break +} +``` \ No newline at end of file diff --git a/docs/description/period_spacing.md b/docs/description/period_spacing.md new file mode 100644 index 0000000..6fd2a66 --- /dev/null +++ b/docs/description/period_spacing.md @@ -0,0 +1,91 @@ +# Period Spacing + +Periods should not be followed by more than one space + +* **Identifier:** `period_spacing` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let pi = 3.2 +``` + +```swift +let pi = Double.pi +``` + +```swift +let pi = Double. pi +``` + +```swift +let pi = Double. pi +``` + +```swift +// A. Single. +``` + +```swift +/// - code: Identifier of the error. Integer. +``` + +```swift +// value: Multiline. +// Comment. +``` + +```swift +/** +Sentence ended in period. + +- Sentence 2 new line characters after. +**/ +``` + +## Triggering Examples + +```swift +/* Only god knows why. ↓ This symbol does nothing. */ +``` + +```swift +// Only god knows why. ↓ This symbol does nothing. +``` + +```swift +// Single. Double. ↓ End. +``` + +```swift +// Single. Double. ↓ Triple. ↓ End. +``` + +```swift +// Triple. ↓ Quad. ↓ End. +``` + +```swift +/// - code: Identifier of the error. ↓ Integer. +``` \ No newline at end of file diff --git a/docs/description/prefer_key_path.md b/docs/description/prefer_key_path.md new file mode 100644 index 0000000..f628f31 --- /dev/null +++ b/docs/description/prefer_key_path.md @@ -0,0 +1,217 @@ +# Prefer Key Path + +Use a key path argument instead of a closure with property access + +* **Identifier:** `prefer_key_path` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.2.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ restrict_to_standard_functions + + true +
+ +## Non Triggering Examples + +```swift +f {} +``` + +```swift +f { $0 } +``` + +```swift +f { $0.a } +``` + +```swift +let f = { $0.a }(b) +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f {} + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f() { g() } + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f { a.b.c } + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f { a, b in a.b } + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f { (a, b) in a.b } + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f { $0.a } g: { $0.b } + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +[1, 2, 3].reduce(1) { $0 + $1 } + +``` + +```swift +f.map(1) { $0.a } +``` + +```swift +f.filter({ $0.a }, x) +``` + +```swift +#Predicate { $0.a } +``` + +```swift +let transform: (Int) -> Int = nil ?? { $0.a } +``` + +## Triggering Examples + +```swift +f.map ↓{ $0.a } +``` + +```swift +f.filter ↓{ $0.a } +``` + +```swift +f.first ↓{ $0.a } +``` + +```swift +f.contains ↓{ $0.a } +``` + +```swift +f.contains(where: ↓{ $0.a }) +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f(↓{ $0.a }) + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f(a: ↓{ $0.b }) + +``` + +```swift +// +// restrict_to_standard_functions: false +// + +f(a: ↓{ a in a.b }, x) + +``` + +```swift +f.map ↓{ a in a.b.c } +``` + +```swift +f.allSatisfy ↓{ (a: A) in a.b } +``` + +```swift +f.first ↓{ (a b: A) in b.c } +``` + +```swift +f.contains ↓{ $0.0.a } +``` + +```swift +f.compactMap ↓{ $0.a.b.c.d } +``` + +```swift +f.flatMap ↓{ $0.a.b } +``` + +```swift +// +// restrict_to_standard_functions: false +// + +let f: (Int) -> Int = ↓{ $0.bigEndian } + +``` + +```swift +transform = ↓{ $0.a } +``` \ No newline at end of file diff --git a/docs/description/prefer_nimble.md b/docs/description/prefer_nimble.md new file mode 100644 index 0000000..d16d661 --- /dev/null +++ b/docs/description/prefer_nimble.md @@ -0,0 +1,62 @@ +# Prefer Nimble + +Prefer Nimble matchers over XCTAssert functions + +* **Identifier:** `prefer_nimble` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +expect(foo) == 1 +``` + +```swift +expect(foo).to(equal(1)) +``` + +## Triggering Examples + +```swift +↓XCTAssertTrue(foo) +``` + +```swift +↓XCTAssertEqual(foo, 2) +``` + +```swift +↓XCTAssertNotEqual(foo, 2) +``` + +```swift +↓XCTAssertNil(foo) +``` + +```swift +↓XCTAssert(foo) +``` + +```swift +↓XCTAssertGreaterThan(foo, 10) +``` \ No newline at end of file diff --git a/docs/description/prefer_self_in_static_references.md b/docs/description/prefer_self_in_static_references.md new file mode 100644 index 0000000..6809fef --- /dev/null +++ b/docs/description/prefer_self_in_static_references.md @@ -0,0 +1,119 @@ +# Prefer Self in Static References + +Use `Self` to refer to the surrounding type name + +* **Identifier:** `prefer_self_in_static_references` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class C { + static let primes = [2, 3, 5, 7] + func isPrime(i: Int) -> Bool { Self.primes.contains(i) } +``` + +```swift +struct T { + static let i = 0 +} +struct S { + static let i = 0 +} +extension T { + static let j = S.i + T.i + static let k = { T.j }() +} +``` + +```swift +class `Self` { + static let i = 0 + func f() -> Int { Self.i } +} +``` + +## Triggering Examples + +```swift +final class CheckCellView: NSTableCellView { + @IBOutlet var checkButton: NSButton! + + override func awakeFromNib() { + checkButton.action = #selector(↓CheckCellView.check(_:)) + } + + @objc func check(_ button: AnyObject?) {} +} +``` + +```swift +class C { + static let i = 1 + var j: Int { + let ii = ↓C.i + return ii + } +} +``` + +```swift +class C { + func f() { + _ = [↓C]() + _ = [Int: ↓C]() + } +} +``` + +```swift +struct S { + let j: Int + static let i = 1 + static func f() -> Int { ↓S.i } + func g() -> Any { ↓S.self } + func h() -> ↓S { ↓S(j: 2) } + func i() -> KeyPath<↓S, Int> { \↓S.j } + func j(@Wrap(-↓S.i, ↓S.i) n: Int = ↓S.i) {} +} +``` + +```swift +struct S { + struct T { + static let i = 3 + } + struct R { + static let j = S.T.i + } + static let h = ↓S.T.i + ↓S.R.j +} +``` + +```swift +enum E { + case A + static func f() -> ↓E { ↓E.A } + static func g() -> ↓E { ↓E.f() } +} +``` \ No newline at end of file diff --git a/docs/description/prefer_self_type_over_type_of_self.md b/docs/description/prefer_self_type_over_type_of_self.md new file mode 100644 index 0000000..831bee4 --- /dev/null +++ b/docs/description/prefer_self_type_over_type_of_self.md @@ -0,0 +1,86 @@ +# Prefer Self Type Over Type of Self + +Prefer `Self` over `type(of: self)` when accessing properties or calling methods + +* **Identifier:** `prefer_self_type_over_type_of_self` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.1.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Foo { + func bar() { + Self.baz() + } +} +``` + +```swift +class Foo { + func bar() { + print(Self.baz) + } +} +``` + +```swift +class A { + func foo(param: B) { + type(of: param).bar() + } +} +``` + +```swift +class A { + func foo() { + print(type(of: self)) + } +} +``` + +## Triggering Examples + +```swift +class Foo { + func bar() { + ↓type(of: self).baz() + } +} +``` + +```swift +class Foo { + func bar() { + print(↓type(of: self).baz) + } +} +``` + +```swift +class Foo { + func bar() { + print(↓Swift.type(of: self).baz) + } +} +``` \ No newline at end of file diff --git a/docs/description/prefer_type_checking.md b/docs/description/prefer_type_checking.md new file mode 100644 index 0000000..6750ac2 --- /dev/null +++ b/docs/description/prefer_type_checking.md @@ -0,0 +1,92 @@ +# Prefer Type Checking + +Prefer `a is X` to `a as? X != nil` + +* **Identifier:** `prefer_type_checking` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = bar as? Foo +``` + +```swift +bar is Foo +``` + +```swift +2*x is X +``` + +```swift +if foo is Bar { + doSomeThing() +} +``` + +```swift +if let bar = foo as? Bar { + foo.run() +} +``` + +```swift +bar as Foo != nil +``` + +```swift +nil != bar as Foo +``` + +```swift +bar as Foo? != nil +``` + +```swift +bar as? Foo? != nil +``` + +## Triggering Examples + +```swift +bar ↓as? Foo != nil +``` + +```swift +2*x as? X != nil +``` + +```swift +if foo ↓as? Bar != nil { + doSomeThing() +} +``` + +```swift +nil != bar ↓as? Foo +``` + +```swift +nil != 2*x ↓as? X +``` \ No newline at end of file diff --git a/docs/description/prefer_zero_over_explicit_init.md b/docs/description/prefer_zero_over_explicit_init.md new file mode 100644 index 0000000..9b6f8c0 --- /dev/null +++ b/docs/description/prefer_zero_over_explicit_init.md @@ -0,0 +1,78 @@ +# Prefer Zero Over Explicit Init + +Prefer `.zero` over explicit init with zero parameters (e.g. `CGPoint(x: 0, y: 0)`) + +* **Identifier:** `prefer_zero_over_explicit_init` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +CGRect(x: 0, y: 0, width: 0, height: 1) +``` + +```swift +CGPoint(x: 0, y: -1) +``` + +```swift +CGSize(width: 2, height: 4) +``` + +```swift +CGVector(dx: -5, dy: 0) +``` + +```swift +UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 1) +``` + +## Triggering Examples + +```swift +↓CGPoint(x: 0, y: 0) +``` + +```swift +↓CGPoint(x: 0.000000, y: 0) +``` + +```swift +↓CGPoint(x: 0.000000, y: 0.000) +``` + +```swift +↓CGRect(x: 0, y: 0, width: 0, height: 0) +``` + +```swift +↓CGSize(width: 0, height: 0) +``` + +```swift +↓CGVector(dx: 0, dy: 0) +``` + +```swift +↓UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) +``` \ No newline at end of file diff --git a/docs/description/prefixed_toplevel_constant.md b/docs/description/prefixed_toplevel_constant.md new file mode 100644 index 0000000..6ea9f47 --- /dev/null +++ b/docs/description/prefixed_toplevel_constant.md @@ -0,0 +1,165 @@ +# Prefixed Top-Level Constant + +Top-level constants should be prefixed by `k` + +* **Identifier:** `prefixed_toplevel_constant` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ only_private + + false +
+ +## Non Triggering Examples + +```swift +private let kFoo = 20.0 +``` + +```swift +public let kFoo = false +``` + +```swift +internal let kFoo = "Foo" +``` + +```swift +let kFoo = true +``` + +```swift +// +// only_private: true +// + +let Foo = true + +``` + +```swift +struct Foo { + let bar = 20.0 +} +``` + +```swift +private var foo = 20.0 +``` + +```swift +public var foo = false +``` + +```swift +internal var foo = "Foo" +``` + +```swift +var foo = true +``` + +```swift +var foo = true, bar = true +``` + +```swift +var foo = true, let kFoo = true +``` + +```swift +let + kFoo = true +``` + +```swift +var foo: Int { + return a + b +} +``` + +```swift +let kFoo = { + return a + b +}() +``` + +```swift +var foo: String { + let bar = "" + return bar +} +``` + +```swift +if condition() { + let result = somethingElse() + print(result) + exit() +} +``` + +```swift +[1, 2, 3, 1000, 4000].forEach { number in + let isSmall = number < 10 + if isSmall { + print("\(number) is a small number") + } +} +``` + +## Triggering Examples + +```swift +private let ↓Foo = 20.0 +``` + +```swift +public let ↓Foo = false +``` + +```swift +internal let ↓Foo = "Foo" +``` + +```swift +let ↓Foo = true +``` + +```swift +let ↓foo = 2, ↓bar = true +``` + +```swift +let + ↓foo = true +``` + +```swift +let ↓foo = { + return a + b +}() +``` \ No newline at end of file diff --git a/docs/description/private_action.md b/docs/description/private_action.md new file mode 100644 index 0000000..fc3da97 --- /dev/null +++ b/docs/description/private_action.md @@ -0,0 +1,132 @@ +# Private Actions + +IBActions should be private + +* **Identifier:** `private_action` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Foo { + @IBAction private func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +struct Foo { + @IBAction private func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +class Foo { + @IBAction fileprivate func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +struct Foo { + @IBAction fileprivate func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +private extension Foo { + @IBAction func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +fileprivate extension Foo { + @IBAction func barButtonTapped(_ sender: UIButton) {} +} +``` + +## Triggering Examples + +```swift +class Foo { + @IBAction ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +struct Foo { + @IBAction ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +class Foo { + @IBAction public ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +struct Foo { + @IBAction public ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +class Foo { + @IBAction internal ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +struct Foo { + @IBAction internal ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +extension Foo { + @IBAction ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +extension Foo { + @IBAction public ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +extension Foo { + @IBAction internal ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +public extension Foo { + @IBAction ↓func barButtonTapped(_ sender: UIButton) {} +} +``` + +```swift +internal extension Foo { + @IBAction ↓func barButtonTapped(_ sender: UIButton) {} +} +``` \ No newline at end of file diff --git a/docs/description/private_outlet.md b/docs/description/private_outlet.md new file mode 100644 index 0000000..4ffa9f8 --- /dev/null +++ b/docs/description/private_outlet.md @@ -0,0 +1,123 @@ +# Private Outlets + +IBOutlets should be private to avoid leaking UIKit to higher layers + +* **Identifier:** `private_outlet` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ allow_private_set + + false +
+ +## Non Triggering Examples + +```swift +class Foo { @IBOutlet private var label: UILabel? } +``` + +```swift +class Foo { @IBOutlet private var label: UILabel! } +``` + +```swift +class Foo { var notAnOutlet: UILabel } +``` + +```swift +class Foo { @IBOutlet weak private var label: UILabel? } +``` + +```swift +class Foo { @IBOutlet private weak var label: UILabel? } +``` + +```swift +class Foo { @IBOutlet fileprivate weak var label: UILabel? } +``` + +```swift +// +// allow_private_set: true +// + +class Foo { @IBOutlet private(set) var label: UILabel? } + +``` + +```swift +// +// allow_private_set: true +// + +class Foo { @IBOutlet private(set) var label: UILabel! } + +``` + +```swift +// +// allow_private_set: true +// + +class Foo { @IBOutlet weak private(set) var label: UILabel? } + +``` + +```swift +// +// allow_private_set: true +// + +class Foo { @IBOutlet private(set) weak var label: UILabel? } + +``` + +```swift +// +// allow_private_set: true +// + +class Foo { @IBOutlet fileprivate(set) weak var label: UILabel? } + +``` + +## Triggering Examples + +```swift +class Foo { @IBOutlet ↓var label: UILabel? } +``` + +```swift +class Foo { @IBOutlet ↓var label: UILabel! } +``` + +```swift +class Foo { @IBOutlet private(set) ↓var label: UILabel? } +``` + +```swift +class Foo { @IBOutlet fileprivate(set) ↓var label: UILabel? } +``` \ No newline at end of file diff --git a/docs/description/private_over_fileprivate.md b/docs/description/private_over_fileprivate.md new file mode 100644 index 0000000..4234846 --- /dev/null +++ b/docs/description/private_over_fileprivate.md @@ -0,0 +1,116 @@ +# Private over Fileprivate + +Prefer `private` over `fileprivate` declarations + +* **Identifier:** `private_over_fileprivate` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ validate_extensions + + false +
+ +## Non Triggering Examples + +```swift +extension String {} +``` + +```swift +private extension String {} +``` + +```swift +public protocol P {} +``` + +```swift +open extension + String {} +``` + +```swift +internal extension String {} +``` + +```swift +package typealias P = Int +``` + +```swift +extension String { + fileprivate func Something(){} +} +``` + +```swift +class MyClass { + fileprivate let myInt = 4 +} +``` + +```swift +actor MyActor { + fileprivate let myInt = 4 +} +``` + +```swift +class MyClass { + fileprivate(set) var myInt = 4 +} +``` + +```swift +struct Outer { + struct Inter { + fileprivate struct Inner {} + } +} +``` + +## Triggering Examples + +```swift +↓fileprivate enum MyEnum {} +``` + +```swift +↓fileprivate class MyClass { + fileprivate(set) var myInt = 4 +} +``` + +```swift +↓fileprivate actor MyActor { + fileprivate let myInt = 4 +} +``` + +```swift + ↓fileprivate func f() {} + ↓fileprivate var x = 0 +``` \ No newline at end of file diff --git a/docs/description/private_subject.md b/docs/description/private_subject.md new file mode 100644 index 0000000..f7e3f9f --- /dev/null +++ b/docs/description/private_subject.md @@ -0,0 +1,264 @@ +# Private Combine Subject + +Combine Subject should be private + +* **Identifier:** `private_subject` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +final class Foobar { + private let goodSubject = PassthroughSubject() +} +``` + +```swift +final class Foobar { + private let goodSubject: PassthroughSubject +} +``` + +```swift +final class Foobar { + fileprivate let goodSubject: PassthroughSubject +} +``` + +```swift +final class Foobar { + private let goodSubject: PassthroughSubject = .init() +} +``` + +```swift +final class Foobar { + private let goodSubject = CurrentValueSubject(false) +} +``` + +```swift +final class Foobar { + private let goodSubject: CurrentValueSubject +} +``` + +```swift +final class Foobar { + fileprivate let goodSubject: CurrentValueSubject +} +``` + +```swift +final class Foobar { + private let goodSubject: CurrentValueSubject = .init("toto") +} +``` + +```swift +final class Foobar { + private let goodSubject = PassthroughSubject, Never>() +} +``` + +```swift +final class Foobar { + private let goodSubject: PassthroughSubject, Never> = .init() +} +``` + +```swift +final class Foobar { + private let goodSubject: CurrentValueSubject, Never> = .init([]) +} +``` + +```swift +final class Foobar { + private let goodSubject = + PassthroughSubject() +} +``` + +```swift +final class Foobar { + private let goodSubject: + PassthroughSubject = .init() +} +``` + +```swift +final class Foobar { + private let goodSubject = + CurrentValueSubject(true) +} +``` + +```swift +final class Foobar { + private let goodSubject: CurrentValueSubject + init() { + let goodSubject = CurrentValueSubject(true) + self.goosSubject = goodSubject + } +} +``` + +```swift +func foo() { + let goodSubject = PassthroughSubject(true) +} +``` + +## Triggering Examples + +```swift +final class Foobar { + let ↓badSubject = PassthroughSubject() +} +``` + +```swift +final class Foobar { + let ↓badSubject: PassthroughSubject +} +``` + +```swift +final class Foobar { + private(set) let ↓badSubject: PassthroughSubject +} +``` + +```swift +final class Foobar { + private(set) let ↓badSubject = PassthroughSubject() +} +``` + +```swift +final class Foobar { + let goodSubject: PassthroughSubject = .init() +} +``` + +```swift +final class Foobar { + private let goodSubject: PassthroughSubject + private(set) let ↓badSubject = PassthroughSubject() + private(set) let ↓anotherBadSubject = PassthroughSubject() +} +``` + +```swift +final class Foobar { + private(set) let ↓badSubject = PassthroughSubject() + private let goodSubject: PassthroughSubject + private(set) let ↓anotherBadSubject = PassthroughSubject() +} +``` + +```swift +final class Foobar { + let ↓badSubject = CurrentValueSubject(true) +} +``` + +```swift +final class Foobar { + let ↓badSubject: CurrentValueSubject +} +``` + +```swift +final class Foobar { + private(set) let ↓badSubject: CurrentValueSubject +} +``` + +```swift +final class Foobar { + private(set) let ↓badSubject = CurrentValueSubject(false) +} +``` + +```swift +final class Foobar { + let goodSubject: CurrentValueSubject = .init("toto") +} +``` + +```swift +final class Foobar { + private let goodSubject: CurrentValueSubject + private(set) let ↓badSubject = CurrentValueSubject(false) + private(set) let ↓anotherBadSubject = CurrentValueSubject(false) +} +``` + +```swift +final class Foobar { + private(set) let ↓badSubject = CurrentValueSubject(false) + private let goodSubject: CurrentValueSubject + private(set) let ↓anotherBadSubject = CurrentValueSubject(true) +} +``` + +```swift +final class Foobar { + let ↓badSubject = PassthroughSubject, Never>() +} +``` + +```swift +final class Foobar { + let ↓badSubject: PassthroughSubject, Never> = .init() +} +``` + +```swift +final class Foobar { + let ↓badSubject: CurrentValueSubject, Never> = .init([]) +} +``` + +```swift +final class Foobar { + let ↓badSubject = + PassthroughSubject() +} +``` + +```swift +final class Foobar { + let ↓badSubject: + PassthroughSubject = .init() +} +``` + +```swift +final class Foobar { + let ↓badSubject = + CurrentValueSubject(true) +} +``` \ No newline at end of file diff --git a/docs/description/private_swiftui_state.md b/docs/description/private_swiftui_state.md new file mode 100644 index 0000000..9da57ff --- /dev/null +++ b/docs/description/private_swiftui_state.md @@ -0,0 +1,242 @@ +# Private SwiftUI State Properties + +SwiftUI state properties should be private + +* **Identifier:** `private_swiftui_state` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +struct MyApp: App { + @State private var isPlaying: Bool = false +} +``` + +```swift +struct MyScene: Scene { + @State private var isPlaying: Bool = false +} +``` + +```swift +struct CofntentView: View { + @State private var isPlaying: Bool = false +} +``` + +```swift +struct ContentView: View { + @State private var isPlaying: Bool = false + + struct InnerView: View { + @State private var showsIndicator: Bool = false + } +} +``` + +```swift +struct MyStruct { + struct ContentView: View { + @State private var isPlaying: Bool = false + } +} +``` + +```swift +struct MyStruct { + struct ContentView: View { + @State private var isPlaying: Bool = false + } + + @State var nonTriggeringState: Bool = false +} +``` + +```swift +struct ContentView: View { + var s: Int { + @State + var s: Int = 3 + return s + } + + var body: some View { Text("") } +} +``` + +```swift +struct ContentView: View { + var isPlaying = false +} +``` + +```swift +struct MyApp: App { + @StateObject private var model = DataModel() +} +``` + +```swift +struct MyScene: Scene { + @StateObject private var model = DataModel() +} +``` + +```swift +struct ContentView: View { + @StateObject private var model = DataModel() +} +``` + +```swift +struct MyStruct { + struct ContentView: View { + @StateObject private var dataModel = DataModel() + } + + @StateObject var nonTriggeringObject = MyModel() +} +``` + +```swift +struct Foo { + @State var bar = false +} +``` + +```swift +class Foo: ObservableObject { + @State var bar = Bar() +} +``` + +```swift +extension MyObject { + struct ContentView: View { + @State private var isPlaying: Bool = false + } +} +``` + +```swift +actor ContentView: View { + @State private var isPlaying: Bool = false +} +``` + +## Triggering Examples + +```swift +struct MyApp: App { + @State ↓var isPlaying: Bool = false +} +``` + +```swift +struct MyScene: Scene { + @State ↓public var isPlaying: Bool = false +} +``` + +```swift +struct ContentView: View { + @State ↓var isPlaying: Bool = false +} +``` + +```swift +struct ContentView: View { + struct InnerView: View { + @State private var showsIndicator: Bool = false + } + + @State ↓var isPlaying: Bool = false +} +``` + +```swift +struct MyStruct { + struct ContentView: View { + @State ↓var isPlaying: Bool = false + } +} +``` + +```swift +struct MyStruct { + struct ContentView: View { + @State ↓var isPlaying: Bool = false + } + + @State var isPlaying: Bool = false +} +``` + +```swift +final class ContentView: View { + @State ↓var isPlaying: Bool = false +} +``` + +```swift +extension MyObject { + struct ContentView: View { + @State ↓var isPlaying: Bool = false + } +} +``` + +```swift +actor ContentView: View { + @State ↓var isPlaying: Bool = false +} +``` + +```swift +struct MyApp: App { + @StateObject ↓var model = DataModel() +} +``` + +```swift +struct MyScene: Scene { + @StateObject ↓var model = DataModel() +} +``` + +```swift +struct ContentView: View { + @StateObject ↓var model = DataModel() +} +``` + +```swift +struct ContentView: View { + @State ↓private(set) var isPlaying = false +``` + +```swift +struct ContentView: View { + @State ↓fileprivate(set) public var isPlaying = false +``` \ No newline at end of file diff --git a/docs/description/private_unit_test.md b/docs/description/private_unit_test.md new file mode 100644 index 0000000..dc76e69 --- /dev/null +++ b/docs/description/private_unit_test.md @@ -0,0 +1,131 @@ +# Private Unit Test + +Unit tests marked private are silently skipped + +* **Identifier:** `private_unit_test` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ test_parent_classes + + ["QuickSpec", "XCTestCase"] +
+ +## Non Triggering Examples + +```swift +class FooTest: XCTestCase { + func test1() {} + internal func test2() {} + public func test3() {} +} +``` + +```swift +internal class FooTest: XCTestCase { + func test1() {} + internal func test2() {} + public func test3() {} +} +``` + +```swift +public class FooTest: XCTestCase { + func test1() {} + internal func test2() {} + public func test3() {} +} +``` + +```swift +@objc private class FooTest: XCTestCase { + @objc private func test1() {} + internal func test2() {} + public func test3() {} +} +``` + +```swift +private class Foo: NSObject { + func test1() {} + internal func test2() {} + public func test3() {} +} +``` + +```swift +private class Foo { + func test1() {} + internal func test2() {} + public func test3() {} +} +``` + +```swift +public class FooTest: XCTestCase { + private func test1(param: Int) {} + private func test2() -> String { "" } + private func atest() {} + private static func test3() {} +} +``` + +## Triggering Examples + +```swift +private ↓class FooTest: XCTestCase { + func test1() {} + internal func test2() {} + public func test3() {} + private func test4() {} +} +``` + +```swift +class FooTest: XCTestCase { + func test1() {} + internal func test2() {} + public func test3() {} + private ↓func test4() {} +} +``` + +```swift +internal class FooTest: XCTestCase { + func test1() {} + internal func test2() {} + public func test3() {} + private ↓func test4() {} +} +``` + +```swift +public class FooTest: XCTestCase { + func test1() {} + internal func test2() {} + public func test3() {} + private ↓func test4() {} +} +``` \ No newline at end of file diff --git a/docs/description/prohibited_interface_builder.md b/docs/description/prohibited_interface_builder.md new file mode 100644 index 0000000..1871cf0 --- /dev/null +++ b/docs/description/prohibited_interface_builder.md @@ -0,0 +1,54 @@ +# Prohibited Interface Builder + +Creating views using Interface Builder should be avoided + +* **Identifier:** `prohibited_interface_builder` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class ViewController: UIViewController { + var label: UILabel! +} +``` + +```swift +class ViewController: UIViewController { + @objc func buttonTapped(_ sender: UIButton) {} +} +``` + +## Triggering Examples + +```swift +class ViewController: UIViewController { + @IBOutlet ↓var label: UILabel! +} +``` + +```swift +class ViewController: UIViewController { + @IBAction ↓func buttonTapped(_ sender: UIButton) {} +} +``` \ No newline at end of file diff --git a/docs/description/prohibited_super_call.md b/docs/description/prohibited_super_call.md new file mode 100644 index 0000000..d4412cd --- /dev/null +++ b/docs/description/prohibited_super_call.md @@ -0,0 +1,109 @@ +# Prohibited Calls to Super + +Some methods should not call super. + +* **Identifier:** `prohibited_super_call` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ excluded + + [] +
+ included + + ["*"] +
+ +## Non Triggering Examples + +```swift +class VC: UIViewController { + override func loadView() { + } +} +``` + +```swift +class NSView { + func updateLayer() { + self.method1() + } +} +``` + +```swift +public class FileProviderExtension: NSFileProviderExtension { + override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) { + guard let identifier = persistentIdentifierForItem(at: url) else { + completionHandler(NSFileProviderError(.noSuchItem)) + return + } + } +} +``` + +## Triggering Examples + +```swift +class VC: UIViewController { + override func loadView() {↓ + super.loadView() + } +} +``` + +```swift +class VC: NSFileProviderExtension { + override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) {↓ + self.method1() + super.providePlaceholder(at:url, completionHandler: completionHandler) + } +} +``` + +```swift +class VC: NSView { + override func updateLayer() {↓ + self.method1() + super.updateLayer() + self.method2() + } +} +``` + +```swift +class VC: NSView { + override func updateLayer() {↓ + defer { + super.updateLayer() + } + } +} +``` \ No newline at end of file diff --git a/docs/description/protocol_property_accessors_order.md b/docs/description/protocol_property_accessors_order.md new file mode 100644 index 0000000..5b27882 --- /dev/null +++ b/docs/description/protocol_property_accessors_order.md @@ -0,0 +1,54 @@ +# Protocol Property Accessors Order + +When declaring properties in protocols, the order of accessors should be `get set` + +* **Identifier:** `protocol_property_accessors_order` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +protocol Foo { + var bar: String { get set } + } +``` + +```swift +protocol Foo { + var bar: String { get } + } +``` + +```swift +protocol Foo { + var bar: String { set } + } +``` + +## Triggering Examples + +```swift +protocol Foo { + var bar: String { ↓set get } + } +``` \ No newline at end of file diff --git a/docs/description/quick_discouraged_call.md b/docs/description/quick_discouraged_call.md new file mode 100644 index 0000000..a79e499 --- /dev/null +++ b/docs/description/quick_discouraged_call.md @@ -0,0 +1,380 @@ +# Quick Discouraged Call + +Discouraged call inside 'describe' and/or 'context' block. + +* **Identifier:** `quick_discouraged_call` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class TotoTests { + override func spec() { + describe("foo") { + let foo = Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + beforeEach { + let foo = Foo() + foo.toto() + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + beforeEach { + let foo = Foo() + foo.toto() + } + afterEach { + let foo = Foo() + foo.toto() + } + describe("bar") { + } + context("bar") { + } + it("bar") { + let foo = Foo() + foo.toto() + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + justBeforeEach { + let foo = Foo() + foo.toto() + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + aroundEach { + let foo = Foo() + foo.toto() + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + itBehavesLike("bar") + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + it("does something") { + let foo = Foo() + foo.toto() + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + afterEach { toto.append(foo) } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + xcontext("foo") { + afterEach { toto.append(foo) } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + xdescribe("foo") { + afterEach { toto.append(foo) } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + xit("does something") { + let foo = Foo() + foo.toto() + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + fcontext("foo") { + afterEach { toto.append(foo) } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + fdescribe("foo") { + afterEach { toto.append(foo) } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + fit("does something") { + let foo = Foo() + foo.toto() + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + fitBehavesLike("foo") + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + xitBehavesLike("foo") + } +} +``` + +## Triggering Examples + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + let foo = ↓Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override static func spec() { + describe("foo") { + let foo = ↓Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + let foo = ↓Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + context("foo") { + let foo = ↓Foo() + } + context("bar") { + let foo = ↓Foo() + ↓foo.bar() + it("does something") { + let foo = Foo() + foo.toto() + } + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + context("foo") { + context("foo") { + beforeEach { + let foo = Foo() + foo.toto() + } + it("bar") { + } + context("foo") { + let foo = ↓Foo() + } + } + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + let foo = ↓Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + sharedExamples("foo") { + let foo = ↓Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + ↓foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + ↓foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + sharedExamples("foo") { + ↓foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + xdescribe("foo") { + let foo = ↓Foo() + } + fdescribe("foo") { + let foo = ↓Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + xcontext("foo") { + let foo = ↓Foo() + } + fcontext("foo") { + let foo = ↓Foo() + } + } +} +``` + +```swift +class TotoTests: QuickSpecSubclass { + override func spec() { + xcontext("foo") { + let foo = ↓Foo() + } + fcontext("foo") { + let foo = ↓Foo() + } + } +} +``` \ No newline at end of file diff --git a/docs/description/quick_discouraged_focused_test.md b/docs/description/quick_discouraged_focused_test.md new file mode 100644 index 0000000..a3bc55c --- /dev/null +++ b/docs/description/quick_discouraged_focused_test.md @@ -0,0 +1,117 @@ +# Quick Discouraged Focused Test + +Non-focused tests won't run as long as this test is focused + +* **Identifier:** `quick_discouraged_focused_test` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + describe("bar") { } + context("bar") { + it("bar") { } + } + it("bar") { } + itBehavesLike("bar") + } + } +} +``` + +## Triggering Examples + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓fdescribe("foo") { } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓fcontext("foo") { } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓fit("foo") { } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + ↓fit("bar") { } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + ↓fit("bar") { } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + context("bar") { + ↓fit("toto") { } + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓fitBehavesLike("foo") + } +} +``` + +```swift +class TotoTests: QuickSpecSubclass { + override func spec() { + ↓fitBehavesLike("foo") + } +} +``` \ No newline at end of file diff --git a/docs/description/quick_discouraged_pending_test.md b/docs/description/quick_discouraged_pending_test.md new file mode 100644 index 0000000..5ed94a8 --- /dev/null +++ b/docs/description/quick_discouraged_pending_test.md @@ -0,0 +1,125 @@ +# Quick Discouraged Pending Test + +This test won't run as long as it's marked pending + +* **Identifier:** `quick_discouraged_pending_test` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + describe("bar") { } + context("bar") { + it("bar") { } + } + it("bar") { } + itBehavesLike("bar") + } + } +} +``` + +## Triggering Examples + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓xdescribe("foo") { } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓xcontext("foo") { } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓xit("foo") { } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + ↓xit("bar") { } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + ↓xit("bar") { } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + context("bar") { + ↓xit("toto") { } + } + } + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓pending("foo") + } +} +``` + +```swift +class TotoTests: QuickSpec { + override func spec() { + ↓xitBehavesLike("foo") + } +} +``` + +```swift +class TotoTests: QuickSpecSubclass { + override func spec() { + ↓xitBehavesLike("foo") + } +} +``` \ No newline at end of file diff --git a/docs/description/raw_value_for_camel_cased_codable_enum.md b/docs/description/raw_value_for_camel_cased_codable_enum.md new file mode 100644 index 0000000..d039c94 --- /dev/null +++ b/docs/description/raw_value_for_camel_cased_codable_enum.md @@ -0,0 +1,119 @@ +# Raw Value for Camel Cased Codable Enum + +Camel cased cases of Codable String enums should have raw values + +* **Identifier:** `raw_value_for_camel_cased_codable_enum` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +enum Numbers: Codable { + case int(Int) + case short(Int16) +} +``` + +```swift +enum Numbers: Int, Codable { + case one = 1 + case two = 2 +} +``` + +```swift +enum Numbers: Double, Codable { + case one = 1.1 + case two = 2.2 +} +``` + +```swift +enum Numbers: String, Codable { + case one = "one" + case two = "two" +} +``` + +```swift +enum Status: String, Codable { + case OK, ACCEPTABLE +} +``` + +```swift +enum Status: String, Codable { + case ok + case maybeAcceptable = "maybe_acceptable" +} +``` + +```swift +enum Status: String { + case ok + case notAcceptable + case maybeAcceptable = "maybe_acceptable" +} +``` + +```swift +enum Status: Int, Codable { + case ok + case notAcceptable + case maybeAcceptable = -1 +} +``` + +## Triggering Examples + +```swift +enum Status: String, Codable { + case ok + case ↓notAcceptable + case maybeAcceptable = "maybe_acceptable" +} +``` + +```swift +enum Status: String, Decodable { + case ok + case ↓notAcceptable + case maybeAcceptable = "maybe_acceptable" +} +``` + +```swift +enum Status: String, Encodable { + case ok + case ↓notAcceptable + case maybeAcceptable = "maybe_acceptable" +} +``` + +```swift +enum Status: String, Codable { + case ok + case ↓notAcceptable + case maybeAcceptable = "maybe_acceptable" +} +``` \ No newline at end of file diff --git a/docs/description/reduce_boolean.md b/docs/description/reduce_boolean.md new file mode 100644 index 0000000..10ab342 --- /dev/null +++ b/docs/description/reduce_boolean.md @@ -0,0 +1,78 @@ +# Reduce Boolean + +Prefer using `.allSatisfy()` or `.contains()` over `reduce(true)` or `reduce(false)`. + +* **Identifier:** `reduce_boolean` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +nums.reduce(0) { $0.0 + $0.1 } +``` + +```swift +nums.reduce(0.0) { $0.0 + $0.1 } +``` + +```swift +nums.reduce(initial: true) { $0.0 && $0.1 == 3 } +``` + +## Triggering Examples + +```swift +let allNines = nums.↓reduce(true) { $0.0 && $0.1 == 9 } +``` + +```swift +let anyNines = nums.↓reduce(false) { $0.0 || $0.1 == 9 } +``` + +```swift +let allValid = validators.↓reduce(true) { $0 && $1(input) } +``` + +```swift +let anyValid = validators.↓reduce(false) { $0 || $1(input) } +``` + +```swift +let allNines = nums.↓reduce(true, { $0.0 && $0.1 == 9 }) +``` + +```swift +let anyNines = nums.↓reduce(false, { $0.0 || $0.1 == 9 }) +``` + +```swift +let allValid = validators.↓reduce(true, { $0 && $1(input) }) +``` + +```swift +let anyValid = validators.↓reduce(false, { $0 || $1(input) }) +``` + +```swift +nums.reduce(into: true) { (r: inout Bool, s) in r = r && (s == 3) } +``` \ No newline at end of file diff --git a/docs/description/reduce_into.md b/docs/description/reduce_into.md new file mode 100644 index 0000000..55e41cc --- /dev/null +++ b/docs/description/reduce_into.md @@ -0,0 +1,139 @@ +# Reduce into + +Prefer `reduce(into:_:)` over `reduce(_:_:)` for copy-on-write types + +* **Identifier:** `reduce_into` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = values.reduce(into: "abc") { $0 += "\($1)" } +``` + +```swift +values.reduce(into: Array()) { result, value in + result.append(value) +} +``` + +```swift +let rows = violations.enumerated().reduce(into: "") { rows, indexAndViolation in + rows.append(generateSingleRow(for: indexAndViolation.1, at: indexAndViolation.0 + 1)) +} +``` + +```swift +zip(group, group.dropFirst()).reduce(into: []) { result, pair in + result.append(pair.0 + pair.1) +} +``` + +```swift +let foo = values.reduce(into: [String: Int]()) { result, value in + result["\(value)"] = value +} +``` + +```swift +let foo = values.reduce(into: Dictionary.init()) { result, value in + result["\(value)"] = value +} +``` + +```swift +let foo = values.reduce(into: [Int](repeating: 0, count: 10)) { result, value in + result.append(value) +} +``` + +```swift +let foo = values.reduce(MyClass()) { result, value in + result.handleValue(value) + return result +} +``` + +## Triggering Examples + +```swift +let bar = values.↓reduce("abc") { $0 + "\($1)" } +``` + +```swift +values.↓reduce(Array()) { result, value in + result += [value] +} +``` + +```swift +[1, 2, 3].↓reduce(Set()) { acc, value in + var result = acc + result.insert(value) + return result +} +``` + +```swift +let rows = violations.enumerated().↓reduce("") { rows, indexAndViolation in + return rows + generateSingleRow(for: indexAndViolation.1, at: indexAndViolation.0 + 1) +} +``` + +```swift +zip(group, group.dropFirst()).↓reduce([]) { result, pair in + result + [pair.0 + pair.1] +} +``` + +```swift +let foo = values.↓reduce([String: Int]()) { result, value in + var result = result + result["\(value)"] = value + return result +} +``` + +```swift +let bar = values.↓reduce(Dictionary.init()) { result, value in + var result = result + result["\(value)"] = value + return result +} +``` + +```swift +let bar = values.↓reduce([Int](repeating: 0, count: 10)) { result, value in + return result + [value] +} +``` + +```swift +extension Data { + var hexString: String { + return ↓reduce("") { (output, byte) -> String in + output + String(format: "%02x", byte) + } + } +} +``` \ No newline at end of file diff --git a/docs/description/redundant_discardable_let.md b/docs/description/redundant_discardable_let.md new file mode 100644 index 0000000..3a0a26f --- /dev/null +++ b/docs/description/redundant_discardable_let.md @@ -0,0 +1,89 @@ +# Redundant Discardable Let + +Prefer `_ = foo()` over `let _ = foo()` when discarding a result from a function + +* **Identifier:** `redundant_discardable_let` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ ignore_swiftui_view_bodies + + false +
+ +## Non Triggering Examples + +```swift +_ = foo() +``` + +```swift +if let _ = foo() { } +``` + +```swift +guard let _ = foo() else { return } +``` + +```swift +let _: ExplicitType = foo() +``` + +```swift +while let _ = SplashStyle(rawValue: maxValue) { maxValue += 1 } +``` + +```swift +async let _ = await foo() +``` + +```swift +// +// ignore_swiftui_view_bodies: true +// + +var body: some View { + let _ = foo() + return Text("Hello, World!") +} + +``` + +## Triggering Examples + +```swift +↓let _ = foo() +``` + +```swift +if _ = foo() { ↓let _ = bar() } +``` + +```swift +var body: some View { + ↓let _ = foo() + Text("Hello, World!") +} +``` \ No newline at end of file diff --git a/docs/description/redundant_nil_coalescing.md b/docs/description/redundant_nil_coalescing.md new file mode 100644 index 0000000..59ad127 --- /dev/null +++ b/docs/description/redundant_nil_coalescing.md @@ -0,0 +1,38 @@ +# Redundant Nil Coalescing + +nil coalescing operator is only evaluated if the lhs is nil, coalescing operator with nil as rhs is redundant + +* **Identifier:** `redundant_nil_coalescing` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +var myVar: Int?; myVar ?? 0 +``` + +## Triggering Examples + +```swift +var myVar: Int? = nil; myVar ↓?? nil +``` \ No newline at end of file diff --git a/docs/description/redundant_objc_attribute.md b/docs/description/redundant_objc_attribute.md new file mode 100644 index 0000000..27c4de5 --- /dev/null +++ b/docs/description/redundant_objc_attribute.md @@ -0,0 +1,294 @@ +# Redundant @objc Attribute + +Objective-C attribute (@objc) is redundant in declaration + +* **Identifier:** `redundant_objc_attribute` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +@objc private var foo: String? {} +``` + +```swift +@IBInspectable private var foo: String? {} +``` + +```swift +@objc private func foo(_ sender: Any) {} +``` + +```swift +@IBAction private func foo(_ sender: Any) {} +``` + +```swift +@GKInspectable private var foo: String! {} +``` + +```swift +private @GKInspectable var foo: String! {} +``` + +```swift +@NSManaged var foo: String! +``` + +```swift +@objc @NSCopying var foo: String! +``` + +```swift +@objcMembers +class Foo { + var bar: Any? + @objc + class Bar: NSObject { + @objc + var foo: Any? + } +} +``` + +```swift +@objc +extension Foo { + var bar: Int { + return 0 + } +} +``` + +```swift +extension Foo { + @objc + var bar: Int { return 0 } +} +``` + +```swift +@objc @IBDesignable +extension Foo { + var bar: Int { return 0 } +} +``` + +```swift +@IBDesignable +extension Foo { + @objc + var bar: Int { return 0 } + var fooBar: Int { return 1 } +} +``` + +```swift +@objcMembers +class Foo: NSObject { + @objc + private var bar: Int { + return 0 + } +} +``` + +```swift +@objcMembers +class Foo { + @objc + class Bar: NSObject { + @objc var foo: Any? + } +} +``` + +```swift +@objcMembers +class Foo: NSObject { + @objc class Bar {} +} +``` + +```swift +extension BlockEditorSettings { + @objc(addElementsObject:) + @NSManaged public func addToElements(_ value: BlockEditorSettingElement) +} +``` + +```swift +@objcMembers +public class Foo: NSObject { + @objc + private func handler(_ notification: Notification) { + } + + func registerForNotifications() { + NotificationCenter.default.addObserver(self, selector: #selector(handler(_:)), name: nil, object: nil) + } +} +``` + +```swift +class Foo: NSObject { } + +@objc extension Foo { + @objc enum Bar: Int { + case bar + } + + var bar: Bar { .bar } +} +``` + +```swift +class Foo: NSObject { } + +@objc extension Foo { + @objc private enum Baz: Int { + case baz + } + + private var baz: Baz { .baz } +} +``` + +```swift +@objcMembers +internal class Foo: NSObject { + @objc + private var baz: Int = 1 + + var x: Any? { + value(forKey: "baz") + } +} +``` + +```swift +@objcMembers +class Foo: NSObject { + @objc enum Bar: Int { + case bar + } +} +``` + +## Triggering Examples + +```swift +↓@objc @IBInspectable private var foo: String? {} +``` + +```swift +@IBInspectable ↓@objc private var foo: String? {} +``` + +```swift +↓@objc @IBAction private func foo(_ sender: Any) {} +``` + +```swift +@IBAction ↓@objc private func foo(_ sender: Any) {} +``` + +```swift +↓@objc @GKInspectable private var foo: String! {} +``` + +```swift +@GKInspectable ↓@objc private var foo: String! {} +``` + +```swift +↓@objc @NSManaged private var foo: String! +``` + +```swift +@NSManaged ↓@objc private var foo: String! +``` + +```swift +↓@objc @IBDesignable class Foo {} +``` + +```swift +@objcMembers +class Foo: NSObject { + ↓@objc var bar: Any? +} +``` + +```swift +@objcMembers +class Foo: NSObject { + ↓@objc var bar: Any? + ↓@objc var foo: Any? + @objc + class Bar { + @objc + var foo: Any? + } +} +``` + +```swift +@objc +extension Foo { + ↓@objc + var bar: Int { + return 0 + } +} +``` + +```swift +@objc @IBDesignable +extension Foo { + ↓@objc + var bar: Int { + return 0 + } +} +``` + +```swift +@objcMembers +class Foo: NSObject { + @objcMembers + class Bar: NSObject { + ↓@objc var foo: Any + } +} +``` + +```swift +@objc +extension Foo { + ↓@objc + private var bar: Int { + return 0 + } +} +``` \ No newline at end of file diff --git a/docs/description/redundant_optional_initialization.md b/docs/description/redundant_optional_initialization.md new file mode 100644 index 0000000..b43f2ae --- /dev/null +++ b/docs/description/redundant_optional_initialization.md @@ -0,0 +1,117 @@ +# Redundant Optional Initialization + +Initializing an optional variable with nil is redundant + +* **Identifier:** `redundant_optional_initialization` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +var myVar: Int? +``` + +```swift +let myVar: Int? = nil +``` + +```swift +var myVar: Int? = 0 +``` + +```swift +func foo(bar: Int? = 0) { } +``` + +```swift +var myVar: Optional +``` + +```swift +let myVar: Optional = nil +``` + +```swift +var myVar: Optional = 0 +``` + +```swift +var foo: Int? { + if bar != nil { } + return 0 +} +``` + +```swift +var foo: Int? = { + if bar != nil { } + return 0 +}() +``` + +```swift +lazy var test: Int? = nil +``` + +```swift +func funcName() { + var myVar: String? +} +``` + +```swift +func funcName() { + let myVar: String? = nil +} +``` + +## Triggering Examples + +```swift +var myVar: Int?↓ = nil +``` + +```swift +var myVar: Optional↓ = nil +``` + +```swift +var myVar: Int?↓=nil +``` + +```swift +var myVar: Optional↓=nil +) +``` + +```swift +var myVar: String?↓ = nil { + didSet { print("didSet") } +} +``` + +```swift +func funcName() { + var myVar: String?↓ = nil +} +``` \ No newline at end of file diff --git a/docs/description/redundant_self_in_closure.md b/docs/description/redundant_self_in_closure.md new file mode 100644 index 0000000..73cf04e --- /dev/null +++ b/docs/description/redundant_self_in_closure.md @@ -0,0 +1,219 @@ +# Redundant Self in Closure + +Explicit use of 'self' is not required + +* **Identifier:** `redundant_self_in_closure` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +struct S { + var x = 0 + func f(_ work: @escaping () -> Void) { work() } + func g() { + f { + x = 1 + f { x = 1 } + g() + } + } +} +``` + +```swift +class C { + var x = 0 + func f(_ work: @escaping () -> Void) { work() } + func g() { + f { [weak self] in + self?.x = 1 + self?.g() + guard let self = self ?? C() else { return } + self?.x = 1 + } + C().f { self.x = 1 } + f { [weak self] in if let self { x = 1 } } + } +} +``` + +```swift +struct S { + var x = 0, error = 0, exception = 0 + var y: Int?, z: Int?, u: Int, v: Int?, w: Int? + func f(_ work: @escaping (Int) -> Void) { work() } + func g(x: Int) { + f { u in + self.x = x + let x = 1 + self.x = 2 + if let y, let v { + self.y = 3 + self.v = 1 + } + guard let z else { + let v = 4 + self.x = 5 + self.v = 6 + return + } + self.z = 7 + while let v { self.v = 8 } + for w in [Int]() { self.w = 9 } + self.u = u + do {} catch { self.error = 10 } + do {} catch let exception { self.exception = 11 } + } + } +} +``` + +```swift +enum E { + case a(Int) + case b(Int, Int) +} +struct S { + var x: E = .a(3), y: Int, z: Int + func f(_ work: @escaping () -> Void) { work() } + func g(x: Int) { + f { + switch x { + case let .a(y): + self.y = 1 + case .b(let y, var z): + self.y = 2 + self.z = 3 + } + } + } +} +``` + +## Triggering Examples + +```swift +struct S { + var x = 0 + func f(_ work: @escaping () -> Void) { work() } + func g() { + f { + ↓self.x = 1 + if ↓self.x == 1 { ↓self.g() } + } + } +} +``` + +```swift +class C { + var x = 0 + func g() { + { + ↓self.x = 1 + ↓self.g() + }() + } +} +``` + +```swift +class C { + var x = 0 + func f(_ work: @escaping () -> Void) { work() } + func g() { + f { [self] in + ↓self.x = 1 + ↓self.g() + f { self.x = 1 } + } + } +} +``` + +```swift +class C { + var x = 0 + func f(_ work: @escaping () -> Void) { work() } + func g() { + f { [unowned self] in ↓self.x = 1 } + f { [self = self] in ↓self.x = 1 } + f { [s = self] in s.x = 1 } + } +} +``` + +```swift +struct S { + var x = 0 + var y: Int?, z: Int?, v: Int?, w: Int? + func f(_ work: @escaping () -> Void) { work() } + func g(w: Int, _ v: Int) { + f { + self.w = 1 + ↓self.x = 2 + if let y { ↓self.x = 3 } + else { ↓self.y = 3 } + guard let z else { + ↓self.z = 4 + ↓self.x = 5 + return + } + ↓self.y = 6 + while let y { ↓self.x = 7 } + for y in [Int]() { ↓self.x = 8 } + self.v = 9 + do { + let x = 10 + self.x = 11 + } + ↓self.x = 12 + } + } +} +``` + +```swift +class C { + var x = 0 + func f(_ work: @escaping () -> Void) { work() } + func g() { + f { [weak self] in + self?.x = 1 + guard let self else { return } + ↓self.x = 1 + } + f { [weak self] in + self?.x = 1 + if let self = self else { ↓self.x = 1 } + self?.x = 1 + } + f { [weak self] in + self?.x = 1 + while let self else { ↓self.x = 1 } + self?.x = 1 + } + } +} +``` \ No newline at end of file diff --git a/docs/description/redundant_sendable.md b/docs/description/redundant_sendable.md new file mode 100644 index 0000000..12ae7e1 --- /dev/null +++ b/docs/description/redundant_sendable.md @@ -0,0 +1,79 @@ +# Redundant Sendable + +Sendable conformance is redundant on an actor-isolated type + +* **Identifier:** `redundant_sendable` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ global_actors + + [] +
+ +## Non Triggering Examples + +```swift +struct S: Sendable {} +``` + +```swift +class C: Sendable {} +``` + +```swift +actor A {} +``` + +```swift +@MainActor struct S {} +``` + +```swift +@MyActor enum E: Sendable { case a } +``` + +```swift +@MainActor protocol P: Sendable {} +``` + +## Triggering Examples + +```swift +@MainActor struct ↓S: Sendable {} +``` + +```swift +actor ↓A: Sendable {} +``` + +```swift +// +// global_actors: ["MyActor"] +// + +@MyActor enum ↓E: Sendable { case a } + +``` \ No newline at end of file diff --git a/docs/description/redundant_set_access_control.md b/docs/description/redundant_set_access_control.md new file mode 100644 index 0000000..c9dbede --- /dev/null +++ b/docs/description/redundant_set_access_control.md @@ -0,0 +1,98 @@ +# Redundant Access Control for Setter + +Property setter access level shouldn't be explicit if it's the same as the variable access level + +* **Identifier:** `redundant_set_access_control` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +private(set) public var foo: Int +``` + +```swift +public let foo: Int +``` + +```swift +public var foo: Int +``` + +```swift +var foo: Int +``` + +```swift +private final class A { + private(set) var value: Int +} +``` + +```swift +extension Color { + public internal(set) static var someColor = Color.anotherColor +} +``` + +## Triggering Examples + +```swift +↓private(set) private var foo: Int +``` + +```swift +↓fileprivate(set) fileprivate var foo: Int +``` + +```swift +↓internal(set) internal var foo: Int +``` + +```swift +↓public(set) public var foo: Int +``` + +```swift +open class Foo { + ↓open(set) open var bar: Int +} +``` + +```swift +class A { + ↓internal(set) var value: Int +} +``` + +```swift +internal class A { + ↓internal(set) var value: Int +} +``` + +```swift +fileprivate class A { + ↓fileprivate(set) var value: Int +} +``` \ No newline at end of file diff --git a/docs/description/redundant_string_enum_value.md b/docs/description/redundant_string_enum_value.md new file mode 100644 index 0000000..e5a0825 --- /dev/null +++ b/docs/description/redundant_string_enum_value.md @@ -0,0 +1,83 @@ +# Redundant String Enum Value + +String enum values can be omitted when they are equal to the enumcase name + +* **Identifier:** `redundant_string_enum_value` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +enum Numbers: String { + case one + case two +} +``` + +```swift +enum Numbers: Int { + case one = 1 + case two = 2 +} +``` + +```swift +enum Numbers: String { + case one = "ONE" + case two = "TWO" +} +``` + +```swift +enum Numbers: String { + case one = "ONE" + case two = "two" +} +``` + +```swift +enum Numbers: String { + case one, two +} +``` + +## Triggering Examples + +```swift +enum Numbers: String { + case one = ↓"one" + case two = ↓"two" +} +``` + +```swift +enum Numbers: String { + case one = ↓"one", two = ↓"two" +} +``` + +```swift +enum Numbers: String { + case one, two = ↓"two" +} +``` \ No newline at end of file diff --git a/docs/description/redundant_type_annotation.md b/docs/description/redundant_type_annotation.md new file mode 100644 index 0000000..3c73146 --- /dev/null +++ b/docs/description/redundant_type_annotation.md @@ -0,0 +1,381 @@ +# Redundant Type Annotation + +Variables should not have redundant type annotation + +* **Identifier:** `redundant_type_annotation` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ ignore_attributes + + ["IBInspectable"] +
+ ignore_properties + + false +
+ consider_default_literal_types_redundant + + false +
+ +## Non Triggering Examples + +```swift +var url = URL() +``` + +```swift +var url: CustomStringConvertible = URL() +``` + +```swift +var one: Int = 1, two: Int = 2, three: Int +``` + +```swift +guard let url = URL() else { return } +``` + +```swift +if let url = URL() { return } +``` + +```swift +let alphanumerics = CharacterSet.alphanumerics +``` + +```swift +var set: Set = Set([]) +``` + +```swift +var set: Set = Set.init([]) +``` + +```swift +var set = Set([]) +``` + +```swift +var set = Set.init([]) +``` + +```swift +guard var set: Set = Set([]) else { return } +``` + +```swift +if var set: Set = Set.init([]) { return } +``` + +```swift +guard var set = Set([]) else { return } +``` + +```swift +if var set = Set.init([]) { return } +``` + +```swift +var one: A = B() +``` + +```swift +var one: A = B() +``` + +```swift +var one: A = B() +``` + +```swift +let a = A.b.c.d +``` + +```swift +let a: B = A.b.c.d +``` + +```swift +enum Direction { + case up + case down +} + +var direction: Direction = .up +``` + +```swift +enum Direction { + case up + case down +} + +var direction = Direction.up +``` + +```swift +// +// ignore_attributes: ["IgnoreMe"] +// + +@IgnoreMe var a: Int = Int(5) + +``` + +```swift +// +// ignore_attributes: ["IgnoreMe"] +// + +var a: Int { + @IgnoreMe let i: Int = Int(1) + return i +} + +``` + +```swift +var bol: Bool = true +``` + +```swift +var dbl: Double = 0.0 +``` + +```swift +var int: Int = 0 +``` + +```swift +var str: String = "str" +``` + +```swift +// +// ignore_properties: true +// + +struct Foo { + var url: URL = URL() + let myVar: Int? = 0, s: String = "" +} + +``` + +## Triggering Examples + +```swift +var url↓:URL=URL() +``` + +```swift +var url↓:URL = URL(string: "") +``` + +```swift +var url↓: URL = URL() +``` + +```swift +let url↓: URL = URL() +``` + +```swift +lazy var url↓: URL = URL() +``` + +```swift +let url↓: URL = URL()! +``` + +```swift +var one: Int = 1, two↓: Int = Int(5), three: Int +``` + +```swift +guard let url↓: URL = URL() else { return } +``` + +```swift +if let url↓: URL = URL() { return } +``` + +```swift +let alphanumerics↓: CharacterSet = CharacterSet.alphanumerics +``` + +```swift +var set↓: Set = Set([]) +``` + +```swift +var set↓: Set = Set.init([]) +``` + +```swift +var set↓: Set = Set([]) +``` + +```swift +var set↓: Set = Set.init([]) +``` + +```swift +guard var set↓: Set = Set([]) else { return } +``` + +```swift +if var set↓: Set = Set.init([]) { return } +``` + +```swift +guard var set↓: Set = Set([]) else { return } +``` + +```swift +if var set↓: Set = Set.init([]) { return } +``` + +```swift +var set↓: Set = Set([]), otherSet: Set +``` + +```swift +var num↓: Int = Int.random(0..<10) +``` + +```swift +let a↓: A = A.b.c.d +``` + +```swift +let a↓: A = A.f().b +``` + +```swift +class ViewController: UIViewController { + func someMethod() { + let myVar↓: Int = Int(5) + } +} +``` + +```swift +// +// ignore_properties: true +// + +class ViewController: UIViewController { + func someMethod() { + let myVar↓: Int = Int(5) + } +} + +``` + +```swift +let a↓: [Int] = [Int]() +``` + +```swift +let a↓: A.B = A.B() +``` + +```swift +enum Direction { + case up + case down +} + +var direction↓: Direction = Direction.up +``` + +```swift +// +// ignore_attributes: ["IgnoreMe"] +// + +@DontIgnoreMe var a↓: Int = Int(5) + +``` + +```swift +// +// ignore_attributes: ["IgnoreMe"] +// + +@IgnoreMe +var a: Int { + let i↓: Int = Int(1) + return i +} + +``` + +```swift +// +// consider_default_literal_types_redundant: true +// + +var bol↓: Bool = true + +``` + +```swift +// +// consider_default_literal_types_redundant: true +// + +var dbl↓: Double = 0.0 + +``` + +```swift +// +// consider_default_literal_types_redundant: true +// + +var int↓: Int = 0 + +``` + +```swift +// +// consider_default_literal_types_redundant: true +// + +var str↓: String = "str" + +``` \ No newline at end of file diff --git a/docs/description/redundant_void_return.md b/docs/description/redundant_void_return.md new file mode 100644 index 0000000..58ebcbf --- /dev/null +++ b/docs/description/redundant_void_return.md @@ -0,0 +1,137 @@ +# Redundant Void Return + +Returning Void in a function declaration is redundant + +* **Identifier:** `redundant_void_return` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ include_closures + + true +
+ +## Non Triggering Examples + +```swift +func foo() {} +``` + +```swift +func foo() -> Int {} +``` + +```swift +func foo() -> Int -> Void {} +``` + +```swift +func foo() -> VoidResponse +``` + +```swift +let foo: (Int) -> Void +``` + +```swift +func foo() -> Int -> () {} +``` + +```swift +let foo: (Int) -> () +``` + +```swift +func foo() -> ()? +``` + +```swift +func foo() -> ()! +``` + +```swift +func foo() -> Void? +``` + +```swift +func foo() -> Void! +``` + +```swift +struct A { + subscript(key: String) { + print(key) + } +} +``` + +```swift +// +// include_closures: false +// + +doSomething { arg -> Void in + print(arg) +} + +``` + +## Triggering Examples + +```swift +func foo()↓ -> Void {} +``` + +```swift +protocol Foo { + func foo()↓ -> Void +} +``` + +```swift +func foo()↓ -> () {} +``` + +```swift +func foo()↓ -> ( ) {} +``` + +```swift +protocol Foo { + func foo()↓ -> () +} +``` + +```swift +doSomething { arg↓ -> () in + print(arg) +} +``` + +```swift +doSomething { arg↓ -> Void in + print(arg) +} +``` \ No newline at end of file diff --git a/docs/description/required_deinit.md b/docs/description/required_deinit.md new file mode 100644 index 0000000..4def541 --- /dev/null +++ b/docs/description/required_deinit.md @@ -0,0 +1,97 @@ +# Required Deinit + +Classes should have an explicit deinit method + +* **Identifier:** `required_deinit` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Apple { + deinit { } +} +``` + +```swift +enum Banana { } +``` + +```swift +protocol Cherry { } +``` + +```swift +struct Damson { } +``` + +```swift +class Outer { + deinit { print("Deinit Outer") } + class Inner { + deinit { print("Deinit Inner") } + } +} +``` + +## Triggering Examples + +```swift +↓class Apple { } +``` + +```swift +↓class Banana: NSObject, Equatable { } +``` + +```swift +↓class Cherry { + // deinit { } +} +``` + +```swift +↓class Damson { + func deinitialize() { } +} +``` + +```swift +class Outer { + func hello() -> String { return "outer" } + deinit { } + ↓class Inner { + func hello() -> String { return "inner" } + } +} +``` + +```swift +↓class Outer { + func hello() -> String { return "outer" } + class Inner { + func hello() -> String { return "inner" } + deinit { } + } +} +``` \ No newline at end of file diff --git a/docs/description/required_enum_case.md b/docs/description/required_enum_case.md new file mode 100644 index 0000000..8f253e6 --- /dev/null +++ b/docs/description/required_enum_case.md @@ -0,0 +1,170 @@ +# Required Enum Case + +Enums conforming to a specified protocol must implement a specific case(s). + +* **Identifier:** `required_enum_case` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ {Protocol Name} + + + + + + + + + + + + + + + +
KeyValue
+ {Case Name 1} + + {warning|error} +
+ {Case Name 2} + + {warning|error} +
+
+ +## Non Triggering Examples + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +enum MyNetworkResponse: String, NetworkResponsable { + case success, error, notConnected +} + +``` + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +enum MyNetworkResponse: String, NetworkResponsable { + case success, error, notConnected(error: Error) +} + +``` + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +enum MyNetworkResponse: String, NetworkResponsable { + case success + case error + case notConnected +} + +``` + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +enum MyNetworkResponse: String, NetworkResponsable { + case success + case error + case notConnected(error: Error) +} + +``` + +## Triggering Examples + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +↓enum MyNetworkResponse: String, NetworkResponsable { + case success, error +} + +``` + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +↓enum MyNetworkResponse: String, NetworkResponsable { + case success, error +} + +``` + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +↓enum MyNetworkResponse: String, NetworkResponsable { + case success + case error +} + +``` + +```swift +// +// NetworkResponsable: +// error: warning +// notConnected: warning +// success: warning +// + +↓enum MyNetworkResponse: String, NetworkResponsable { + case success + case error +} + +``` \ No newline at end of file diff --git a/docs/description/return_arrow_whitespace.md b/docs/description/return_arrow_whitespace.md new file mode 100644 index 0000000..07177e6 --- /dev/null +++ b/docs/description/return_arrow_whitespace.md @@ -0,0 +1,127 @@ +# Returning Whitespace + +Return arrow and return type should be separated by a single space or on a separate line + +* **Identifier:** `return_arrow_whitespace` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func abc() -> Int {} +``` + +```swift +func abc() -> [Int] {} +``` + +```swift +func abc() -> (Int, Int) {} +``` + +```swift +var abc = {(param: Int) -> Void in } +``` + +```swift +func abc() -> + Int {} +``` + +```swift +func abc() + -> Int {} +``` + +```swift +func reallyLongFunctionMethods(withParam1: Int, param2: String, param3: Bool) where T: AGenericConstraint + -> Int { + return 1 +} +``` + +```swift +typealias SuccessBlock = ((Data) -> Void) +``` + +## Triggering Examples + +```swift +func abc()↓->Int {} +``` + +```swift +func abc()↓->[Int] {} +``` + +```swift +func abc()↓->(Int, Int) {} +``` + +```swift +func abc()↓-> Int {} +``` + +```swift +func abc()↓-> Int {} +``` + +```swift +func abc()↓ ->Int {} +``` + +```swift +func abc()↓ -> Int {} +``` + +```swift +var abc = {(param: Int)↓ ->Bool in } +``` + +```swift +var abc = {(param: Int)↓->Bool in } +``` + +```swift +typealias SuccessBlock = ((Data)↓->Void) +``` + +```swift +func abc() + ↓-> Int {} +``` + +```swift +func abc() + ↓-> Int {} +``` + +```swift +func abc()↓ -> + Int {} +``` + +```swift +func abc()↓ -> +Int {} +``` \ No newline at end of file diff --git a/docs/description/return_value_from_void_function.md b/docs/description/return_value_from_void_function.md new file mode 100644 index 0000000..b0fac53 --- /dev/null +++ b/docs/description/return_value_from_void_function.md @@ -0,0 +1,320 @@ +# Return Value from Void Function + +Returning values from Void functions should be avoided + +* **Identifier:** `return_value_from_void_function` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.1.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func foo() { + return +} +``` + +```swift +func foo() { + return /* a comment */ +} +``` + +```swift +func foo() -> Int { + return 1 +} +``` + +```swift +func foo() -> Void { + if condition { + return + } + bar() +} +``` + +```swift +func foo() { + return; + bar() +} +``` + +```swift +func test() {} +``` + +```swift +init?() { + guard condition else { + return nil + } +} +``` + +```swift +init?(arg: String?) { + guard arg != nil else { + return nil + } +} +``` + +```swift +func test() { + guard condition else { + return + } +} +``` + +```swift +func test() -> Result { + func other() {} + func otherVoid() -> Void {} +} +``` + +```swift +func test() -> Int? { + return nil +} +``` + +```swift +func test() { + if bar { + print("") + return + } + let foo = [1, 2, 3].filter { return true } + return +} +``` + +```swift +func test() { + guard foo else { + bar() + return + } +} +``` + +```swift +func spec() { + var foo: Int { + return 0 + } +``` + +```swift +func f() -> () { g() } +``` + +```swift +func f() { g() } +``` + +```swift +func f() { { return g() }() } +``` + +```swift +func f() { + func g() -> Int { + return 1 + } +} +``` + +```swift +init?() { return nil } +``` + +```swift +func f() { + var i: Int { return 1 } +} +``` + +## Triggering Examples + +```swift +func foo() { + ↓return bar() +} +``` + +```swift +func foo() -> () { + ↓return self.bar() +} +``` + +```swift +func foo() -> Void { + ↓return bar() +} +``` + +```swift +func foo() -> Void { + ↓return /* comment */ bar() +} +``` + +```swift +func foo() { + ↓return + self.bar() +} +``` + +```swift +func foo() { + variable += 1 + ↓return + variable += 1 +} +``` + +```swift +func initThing() { + guard foo else { + ↓return print("") + } +} +``` + +```swift +// Leading comment +func test() { + guard condition else { + ↓return assertionfailure("") + } +} +``` + +```swift +func test() -> Result { + func other() { + guard false else { + ↓return assertionfailure("") + } + } + func otherVoid() -> Void {} +} +``` + +```swift +func test() { + guard conditionIsTrue else { + sideEffects() + return // comment + } + guard otherCondition else { + ↓return assertionfailure("") + } + differentSideEffect() +} +``` + +```swift +func test() { + guard otherCondition else { + ↓return assertionfailure(""); // comment + } + differentSideEffect() +} +``` + +```swift +func test() { + if x { + ↓return foo() + } + bar() +} +``` + +```swift +func test() { + switch x { + case .a: + ↓return foo() // return to skip baz() + case .b: + bar() + } + baz() +} +``` + +```swift +func test() { + if check { + if otherCheck { + ↓return foo() + } + } + bar() +} +``` + +```swift +func test() { + ↓return foo() +} +``` + +```swift +func test() { + ↓return foo({ + return bar() + }) +} +``` + +```swift +func test() { + guard x else { + ↓return foo() + } + bar() +} +``` + +```swift +func test() { + let closure: () -> () = { + return assert() + } + if check { + if otherCheck { + return // comments are fine + } + } + ↓return foo() +} +``` \ No newline at end of file diff --git a/docs/description/self_binding.md b/docs/description/self_binding.md new file mode 100644 index 0000000..cef9ab7 --- /dev/null +++ b/docs/description/self_binding.md @@ -0,0 +1,124 @@ +# Self Binding + +Re-bind `self` to a consistent identifier name. + +* **Identifier:** `self_binding` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ bind_identifier + + "self" +
+ +## Non Triggering Examples + +```swift +if let self = self { return } +``` + +```swift +guard let self = self else { return } +``` + +```swift +if let this = this { return } +``` + +```swift +guard let this = this else { return } +``` + +```swift +// +// bind_identifier: "this" +// + +if let this = self { return } + +``` + +```swift +// +// bind_identifier: "this" +// + +guard let this = self else { return } + +``` + +## Triggering Examples + +```swift +if let ↓`self` = self { return } +``` + +```swift +guard let ↓`self` = self else { return } +``` + +```swift +if let ↓this = self { return } +``` + +```swift +guard let ↓this = self else { return } +``` + +```swift +// +// bind_identifier: "this" +// + +if let ↓self = self { return } + +``` + +```swift +// +// bind_identifier: "this" +// + +guard let ↓self = self else { return } + +``` + +```swift +// +// bind_identifier: "this" +// + +if let ↓self { return } + +``` + +```swift +// +// bind_identifier: "this" +// + +guard let ↓self else { return } + +``` \ No newline at end of file diff --git a/docs/description/self_in_property_initialization.md b/docs/description/self_in_property_initialization.md new file mode 100644 index 0000000..1f980a7 --- /dev/null +++ b/docs/description/self_in_property_initialization.md @@ -0,0 +1,90 @@ +# Self in Property Initialization + +`self` refers to the unapplied `NSObject.self()` method, which is likely not expected; make the variable `lazy` to be able to refer to the current instance or use `ClassName.self` + +* **Identifier:** `self_in_property_initialization` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class View: UIView { + let button: UIButton = { + return UIButton() + }() +} +``` + +```swift +class View: UIView { + lazy var button: UIButton = { + let button = UIButton() + button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside) + return button + }() +} +``` + +```swift +class View: UIView { + var button: UIButton = { + let button = UIButton() + button.addTarget(otherObject, action: #selector(didTapButton), for: .touchUpInside) + return button + }() +} +``` + +```swift +class View: UIView { + private let collectionView: UICollectionView = { + let layout = UICollectionViewFlowLayout() + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + collectionView.registerReusable(Cell.self) + + return collectionView + }() +} +``` + +## Triggering Examples + +```swift +class View: UIView { + ↓var button: UIButton = { + let button = UIButton() + button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside) + return button + }() +} +``` + +```swift +class View: UIView { + ↓let button: UIButton = { + let button = UIButton() + button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside) + return button + }() +} +``` \ No newline at end of file diff --git a/docs/description/shorthand_argument.md b/docs/description/shorthand_argument.md new file mode 100644 index 0000000..a45cbd6 --- /dev/null +++ b/docs/description/shorthand_argument.md @@ -0,0 +1,131 @@ +# Shorthand Argument + +Shorthand arguments like `$0`, `$1`, etc. in closures can be confusing. Avoid using them too far away from the beginning of the closure. Optionally, while usage of a single shorthand argument is okay, more than one or complex ones with field accesses might increase the risk of obfuscation. + +* **Identifier:** `shorthand_argument` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ allow_until_line_after_opening_brace + + 4 +
+ always_disallow_more_than_one + + false +
+ always_disallow_member_access + + false +
+ +## Non Triggering Examples + +```swift +f { $0 } +``` + +```swift +f { + $0 + + $1 + + $2 +} +``` + +```swift +f { $0.a + $0.b } +``` + +```swift +// +// allow_until_line_after_opening_brace: 1 +// + +f { + $0 + + g { $0 } + +``` + +## Triggering Examples + +```swift +f { + $0 + + $1 + + $2 + + + ↓$0 +} +``` + +```swift +// +// allow_until_line_after_opening_brace: 5 +// + +f { + $0 + + $1 + + $2 + + 5 + + $0 + + ↓$1 +} + +``` + +```swift +// +// always_disallow_more_than_one: true +// + +f { ↓$0 + ↓$1 } + +``` + +```swift +// +// allow_until_line_after_opening_brace: 3 +// always_disallow_member_access: true +// + +f { + ↓$0.a + + ↓$0.b + + $1 + + ↓$2.c +} + +``` \ No newline at end of file diff --git a/docs/description/shorthand_operator.md b/docs/description/shorthand_operator.md new file mode 100644 index 0000000..9ddcf23 --- /dev/null +++ b/docs/description/shorthand_operator.md @@ -0,0 +1,109 @@ +# Shorthand Operator + +Prefer shorthand operators (+=, -=, *=, /=) over doing the operation and assigning + +* **Identifier:** `shorthand_operator` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +foo -= 1 +``` + +```swift +foo += variable +``` + +```swift +foo *= bar.method() +``` + +```swift +self.foo = foo / 1 +``` + +```swift +foo = self.foo + 1 +``` + +```swift +page = ceilf(currentOffset * pageWidth) +``` + +```swift +foo = aMethod(foo / bar) +``` + +```swift +foo = aMethod(bar + foo) +``` + +```swift +public func -= (lhs: inout Foo, rhs: Int) { + lhs = lhs - rhs +} +``` + +```swift +var helloWorld = "world!" + helloWorld = "Hello, " + helloWorld +``` + +```swift +angle = someCheck ? angle : -angle +``` + +```swift +seconds = seconds * 60 + value +``` + +## Triggering Examples + +```swift +↓foo = foo * 1 +``` + +```swift +↓foo = foo / aVariable +``` + +```swift +↓foo = foo - bar.method() +``` + +```swift +↓foo.aProperty = foo.aProperty - 1 +``` + +```swift +↓self.aProperty = self.aProperty * 1 +``` + +```swift +↓n = n + i / outputLength +``` + +```swift +↓n = n - i / outputLength +``` \ No newline at end of file diff --git a/docs/description/shorthand_optional_binding.md b/docs/description/shorthand_optional_binding.md new file mode 100644 index 0000000..0866a86 --- /dev/null +++ b/docs/description/shorthand_optional_binding.md @@ -0,0 +1,60 @@ +# Shorthand Optional Binding + +Use shorthand syntax for optional binding + +* **Identifier:** `shorthand_optional_binding` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.7.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +if let i {} +if let i = a {} +guard let i = f() else {} +if var i = i() {} +if let i = i as? Foo {} +guard let `self` = self else {} +while var i { i = nil } +``` + +## Triggering Examples + +```swift +if ↓let i = i {} +if ↓let self = self {} +if ↓var `self` = `self` {} +if i > 0, ↓let j = j {} +if ↓let i = i, ↓var j = j {} +``` + +```swift +guard ↓let i = i else {} +guard ↓let self = self else {} +guard ↓var `self` = `self` else {} +guard i > 0, ↓let j = j else {} +guard ↓let i = i, ↓var j = j else {} +``` + +```swift +while ↓var i = i { i = nil } +``` \ No newline at end of file diff --git a/docs/description/single_test_class.md b/docs/description/single_test_class.md new file mode 100644 index 0000000..17a31cc --- /dev/null +++ b/docs/description/single_test_class.md @@ -0,0 +1,89 @@ +# Single Test Class + +Test files should contain a single QuickSpec or XCTestCase class. + +* **Identifier:** `single_test_class` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ test_parent_classes + + ["QuickSpec", "XCTestCase"] +
+ +## Non Triggering Examples + +```swift +class FooTests { } +``` + +```swift +class FooTests: QuickSpec { } +``` + +```swift +class FooTests: XCTestCase { } +``` + +## Triggering Examples + +```swift +↓class FooTests: QuickSpec { } +↓class BarTests: QuickSpec { } +``` + +```swift +↓class FooTests: QuickSpec { } +↓class BarTests: QuickSpec { } +↓class TotoTests: QuickSpec { } +``` + +```swift +↓class FooTests: XCTestCase { } +↓class BarTests: XCTestCase { } +``` + +```swift +↓class FooTests: XCTestCase { } +↓class BarTests: XCTestCase { } +↓class TotoTests: XCTestCase { } +``` + +```swift +↓class FooTests: QuickSpec { } +↓class BarTests: XCTestCase { } +``` + +```swift +↓class FooTests: QuickSpec { } +↓class BarTests: XCTestCase { } +class TotoTests { } +``` + +```swift +final ↓class FooTests: QuickSpec { } +↓class BarTests: XCTestCase { } +class TotoTests { } +``` \ No newline at end of file diff --git a/docs/description/sorted_enum_cases.md b/docs/description/sorted_enum_cases.md new file mode 100644 index 0000000..f688822 --- /dev/null +++ b/docs/description/sorted_enum_cases.md @@ -0,0 +1,138 @@ +# Sorted Enum Cases + +Enum cases should be sorted + +* **Identifier:** `sorted_enum_cases` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +enum foo { + case a + case b + case c +} +``` + +```swift +enum foo { + case example + case exBoyfriend +} +``` + +```swift +enum foo { + case a + case B + case c +} +``` + +```swift +enum foo { + case a, b, c +} +``` + +```swift +enum foo { + case a + case b, c +} +``` + +```swift +enum foo { + case a(foo: Foo) + case b(String), c +} +``` + +```swift +enum foo { + case a + case b, C, d +} +``` + +```swift +@frozen +enum foo { + case b + case a + case c, f, d +} +``` + +## Triggering Examples + +```swift +enum foo { + ↓case b + ↓case a + case c +} +``` + +```swift +enum foo { + ↓case B + ↓case a + case c +} +``` + +```swift +enum foo { + case ↓b, ↓a, c +} +``` + +```swift +enum foo { + case ↓B, ↓a, c +} +``` + +```swift +enum foo { + ↓case b, c + ↓case a +} +``` + +```swift +enum foo { + case a + case b, ↓d, ↓c +} +``` + +```swift +enum foo { + case a(foo: Foo) + case ↓c, ↓b(String) +} +``` \ No newline at end of file diff --git a/docs/description/sorted_first_last.md b/docs/description/sorted_first_last.md new file mode 100644 index 0000000..1f24002 --- /dev/null +++ b/docs/description/sorted_first_last.md @@ -0,0 +1,150 @@ +# Min or Max over Sorted First or Last + +Prefer using `min()` or `max()` over `sorted().first` or `sorted().last` + +* **Identifier:** `sorted_first_last` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** performance +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let min = myList.min() +``` + +```swift +let min = myList.min(by: { $0 < $1 }) +``` + +```swift +let min = myList.min(by: >) +``` + +```swift +let max = myList.max() +``` + +```swift +let max = myList.max(by: { $0 < $1 }) +``` + +```swift +let message = messages.sorted(byKeyPath: #keyPath(Message.timestamp)).last +``` + +```swift +let message = messages.sorted(byKeyPath: "timestamp", ascending: false).first +``` + +```swift +myList.sorted().firstIndex(of: key) +``` + +```swift +myList.sorted().lastIndex(of: key) +``` + +```swift +myList.sorted().firstIndex(where: someFunction) +``` + +```swift +myList.sorted().lastIndex(where: someFunction) +``` + +```swift +myList.sorted().firstIndex { $0 == key } +``` + +```swift +myList.sorted().lastIndex { $0 == key } +``` + +```swift +myList.sorted().first(where: someFunction) +``` + +```swift +myList.sorted().last(where: someFunction) +``` + +```swift +myList.sorted().first { $0 == key } +``` + +```swift +myList.sorted().last { $0 == key } +``` + +## Triggering Examples + +```swift +↓myList.sorted().first +``` + +```swift +↓myList.sorted(by: { $0.description < $1.description }).first +``` + +```swift +↓myList.sorted(by: >).first +``` + +```swift +↓myList.map { $0 + 1 }.sorted().first +``` + +```swift +↓myList.sorted(by: someFunction).first +``` + +```swift +↓myList.map { $0 + 1 }.sorted { $0.description < $1.description }.first +``` + +```swift +↓myList.sorted().last +``` + +```swift +↓myList.sorted().last?.something() +``` + +```swift +↓myList.sorted(by: { $0.description < $1.description }).last +``` + +```swift +↓myList.map { $0 + 1 }.sorted().last +``` + +```swift +↓myList.sorted(by: someFunction).last +``` + +```swift +↓myList.map { $0 + 1 }.sorted { $0.description < $1.description }.last +``` + +```swift +↓myList.map { $0 + 1 }.sorted { $0.first < $1.first }.last +``` \ No newline at end of file diff --git a/docs/description/sorted_imports.md b/docs/description/sorted_imports.md new file mode 100644 index 0000000..9fec690 --- /dev/null +++ b/docs/description/sorted_imports.md @@ -0,0 +1,124 @@ +# Sorted Imports + +Imports should be sorted + +* **Identifier:** `sorted_imports` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ grouping + + names +
+ +## Non Triggering Examples + +```swift +import AAA +import BBB +import CCC +import DDD +``` + +```swift +import Alamofire +import API +``` + +```swift +import labc +import Ldef +``` + +```swift +import BBB +// comment +import AAA +import CCC +``` + +```swift +@testable import AAA +import CCC +``` + +```swift +import AAA +@testable import CCC +``` + +```swift +import EEE.A +import FFF.B +#if os(Linux) +import DDD.A +import EEE.B +#else +import CCC +import DDD.B +#endif +import AAA +import BBB +``` + +## Triggering Examples + +```swift +import AAA +import ZZZ +import ↓BBB +import CCC +``` + +```swift +import DDD +// comment +import CCC +import ↓AAA +``` + +```swift +@testable import CCC +import ↓AAA +``` + +```swift +import CCC +@testable import ↓AAA +``` + +```swift +import FFF.B +import ↓EEE.A +#if os(Linux) +import DDD.A +import EEE.B +#else +import DDD.B +import ↓CCC +#endif +import AAA +import BBB +``` \ No newline at end of file diff --git a/docs/description/statement_position.md b/docs/description/statement_position.md new file mode 100644 index 0000000..07e0dcf --- /dev/null +++ b/docs/description/statement_position.md @@ -0,0 +1,86 @@ +# Statement Position + +Else and catch should be on the same line, one space after the previous declaration + +* **Identifier:** `statement_position` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ statement_mode + + default +
+ +## Non Triggering Examples + +```swift +} else if { +``` + +```swift +} else { +``` + +```swift +} catch { +``` + +```swift +"}else{" +``` + +```swift +struct A { let catchphrase: Int } +let a = A( + catchphrase: 0 +) +``` + +```swift +struct A { let `catch`: Int } +let a = A( + `catch`: 0 +) +``` + +## Triggering Examples + +```swift +↓}else if { +``` + +```swift +↓} else { +``` + +```swift +↓} +catch { +``` + +```swift +↓} + catch { +``` \ No newline at end of file diff --git a/docs/description/static_operator.md b/docs/description/static_operator.md new file mode 100644 index 0000000..c0d31e8 --- /dev/null +++ b/docs/description/static_operator.md @@ -0,0 +1,100 @@ +# Static Operator + +Operators should be declared as static functions, not free functions + +* **Identifier:** `static_operator` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class A: Equatable { + static func == (lhs: A, rhs: A) -> Bool { + return false + } +``` + +```swift +class A: Equatable { + static func == (lhs: A, rhs: A) -> Bool { + return false + } +``` + +```swift +public extension Array where Element == Rule { + static func == (lhs: Array, rhs: Array) -> Bool { + if lhs.count != rhs.count { return false } + return !zip(lhs, rhs).contains { !$0.0.isEqualTo($0.1) } + } +} +``` + +```swift +private extension Optional where Wrapped: Comparable { + static func < (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (lhs?, rhs?): + return lhs < rhs + case (nil, _?): + return true + default: + return false + } + } +} +``` + +## Triggering Examples + +```swift +↓func == (lhs: A, rhs: A) -> Bool { + return false +} +``` + +```swift +↓func == (lhs: A, rhs: A) -> Bool { + return false +} +``` + +```swift +↓func == (lhs: [Rule], rhs: [Rule]) -> Bool { + if lhs.count != rhs.count { return false } + return !zip(lhs, rhs).contains { !$0.0.isEqualTo($0.1) } +} +``` + +```swift +private ↓func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (lhs?, rhs?): + return lhs < rhs + case (nil, _?): + return true + default: + return false + } +} +``` \ No newline at end of file diff --git a/docs/description/static_over_final_class.md b/docs/description/static_over_final_class.md new file mode 100644 index 0000000..3d456b8 --- /dev/null +++ b/docs/description/static_over_final_class.md @@ -0,0 +1,98 @@ +# Static Over Final Class + +Prefer `static` over `class` when the declaration is not allowed to be overridden in child classes due to its context being final. Likewise, the compiler complains about `open` being used in `final` classes. + +* **Identifier:** `static_over_final_class` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class C { + static func f() {} +} +``` + +```swift +class C { + static var i: Int { 0 } +} +``` + +```swift +class C { + static subscript(_: Int) -> Int { 0 } +} +``` + +```swift +class C { + class func f() {} +} +``` + +```swift +final class C {} +``` + +```swift +final class C { + class D { + class func f() {} + } +} +``` + +## Triggering Examples + +```swift +class C { + ↓final class func f() {} +} +``` + +```swift +class C { + ↓final class var i: Int { 0 } +} +``` + +```swift +class C { + ↓final class subscript(_: Int) -> Int { 0 } +} +``` + +```swift +final class C { + ↓class func f() {} +} +``` + +```swift +class C { + final class D { + ↓class func f() {} + } +} +``` \ No newline at end of file diff --git a/docs/description/strict_fileprivate.md b/docs/description/strict_fileprivate.md new file mode 100644 index 0000000..2811958 --- /dev/null +++ b/docs/description/strict_fileprivate.md @@ -0,0 +1,99 @@ +# Strict Fileprivate + +`fileprivate` should be avoided + +* **Identifier:** `strict_fileprivate` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +extension String {} +``` + +```swift +private extension String {} +``` + +```swift +public + extension String { + var i: Int { 1 } + } +``` + +```swift + private enum E { + func f() {} + } +``` + +```swift + public struct S { + internal let i: Int + } +``` + +```swift + open class C { + private func f() {} + } +``` + +```swift + internal actor A {} +``` + +## Triggering Examples + +```swift + ↓fileprivate class C { + ↓fileprivate func f() {} + } +``` + +```swift + ↓fileprivate extension String { + ↓fileprivate var isSomething: Bool { self == "something" } + } +``` + +```swift + ↓fileprivate actor A { + ↓fileprivate let i = 1 + } +``` + +```swift + ↓fileprivate struct C { + ↓fileprivate(set) var myInt = 4 + } +``` + +```swift + struct Outter { + struct Inter { + ↓fileprivate struct Inner {} + } + } +``` \ No newline at end of file diff --git a/docs/description/strong_iboutlet.md b/docs/description/strong_iboutlet.md new file mode 100644 index 0000000..87240c1 --- /dev/null +++ b/docs/description/strong_iboutlet.md @@ -0,0 +1,60 @@ +# Strong IBOutlet + +@IBOutlets shouldn't be declared as weak + +* **Identifier:** `strong_iboutlet` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class ViewController: UIViewController { + @IBOutlet var label: UILabel? +} +``` + +```swift +class ViewController: UIViewController { + weak var label: UILabel? +} +``` + +## Triggering Examples + +```swift +class ViewController: UIViewController { + @IBOutlet ↓weak var label: UILabel? +} +``` + +```swift +class ViewController: UIViewController { + @IBOutlet ↓unowned var label: UILabel! +} +``` + +```swift +class ViewController: UIViewController { + @IBOutlet ↓weak var textField: UITextField? +} +``` \ No newline at end of file diff --git a/docs/description/superfluous_disable_command.md b/docs/description/superfluous_disable_command.md new file mode 100644 index 0000000..1169eb3 --- /dev/null +++ b/docs/description/superfluous_disable_command.md @@ -0,0 +1,50 @@ +# Superfluous Disable Command + +SwiftLint 'disable' commands are superfluous when the disabled rule would not have triggered a violation in the disabled region. Use " - " if you wish to document a command. + +* **Identifier:** `superfluous_disable_command` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let abc:Void // swiftlint:disable:this colon +``` + +```swift +// swiftlint:disable colon +let abc:Void +// swiftlint:enable colon +``` + +## Triggering Examples + +```swift +let abc: Void // swiftlint:disable:this colon +``` + +```swift +// swiftlint:disable colon +let abc: Void +// swiftlint:enable colon +``` \ No newline at end of file diff --git a/docs/description/superfluous_else.md b/docs/description/superfluous_else.md new file mode 100644 index 0000000..89a9b47 --- /dev/null +++ b/docs/description/superfluous_else.md @@ -0,0 +1,140 @@ +# Superfluous Else + +Else branches should be avoided when the previous if-block exits the current scope + +* **Identifier:** `superfluous_else` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +if i > 0 { + // comment +} else if i < 12 { + return 2 +} else { + return 3 +} +``` + +```swift +if i > 0 { + let a = 1 + if a > 1 { + // comment + } else { + return 1 + } + // comment +} else { + return 3 +} +``` + +```swift +if i > 0 { + if a > 1 { + return 1 + } +} else { + return 3 +} +``` + +```swift +for i in list { + if i > 12 { + // Do nothing + } else { + continue + } + if i > 14 { + // Do nothing + } else if i > 13 { + break + } +} +``` + +```swift +if #available(iOS 13, *) { + return +} else { + deprecatedFunction() +} +``` + +## Triggering Examples + +```swift +if i > 0 { + return 1 + // comment +} ↓else { + return 2 +} +``` + +```swift +if i > 0 { + return 1 +} ↓else if i < 12 { + return 2 +} ↓else if i > 18 { + return 3 +} +``` + +```swift +if i > 0 { + if i < 12 { + return 5 + } ↓else { + if i > 11 { + return 6 + } ↓else { + return 7 + } + } +} ↓else if i < 12 { + return 2 +} ↓else if i < 24 { + return 8 +} ↓else { + return 3 +} +``` + +```swift +for i in list { + if i > 13 { + return + } ↓else if i > 12 { + continue + } ↓else if i > 11 { + break + } ↓else { + throw error + } +} +``` \ No newline at end of file diff --git a/docs/description/switch_case_alignment.md b/docs/description/switch_case_alignment.md new file mode 100644 index 0000000..64c3265 --- /dev/null +++ b/docs/description/switch_case_alignment.md @@ -0,0 +1,234 @@ +# Switch and Case Statement Alignment + +Case statements should vertically align with their closing brace, or indented if configured otherwise. + +* **Identifier:** `switch_case_alignment` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ indented_cases + + false +
+ ignore_one_liners + + false +
+ +## Non Triggering Examples + +```swift +switch someBool { +case true: // case 1 + print('red') +case false: + /* + case 2 + */ + if case let .someEnum(val) = someFunc() { + print('blue') + } +} +enum SomeEnum { + case innocent +} +``` + +```swift +if aBool { + switch someBool { + case true: + print('red') + case false: + print('blue') + } +} +``` + +```swift +switch someInt { +// comments ignored +case 0: + // zero case + print('Zero') +case 1: + print('One') +default: + print('Some other number') +} +``` + +```swift +func f() -> Int { + return switch i { + case 1: 1 + default: 2 + } +} +``` + +```swift +// +// ignore_one_liners: true +// + +switch i { case .x: 1 default: 0 } + +``` + +```swift +// +// ignore_one_liners: true +// + +let a = switch i { case .x: 1 default: 0 } + +``` + +## Triggering Examples + +```swift +switch someBool { + ↓case true: + print("red") + ↓case false: + print("blue") +} +``` + +```swift +if aBool { + switch someBool { + ↓case true: + print('red') + ↓case false: + print('blue') + } +} +``` + +```swift +switch someInt { + ↓case 0: + print('Zero') + ↓case 1: + print('One') + ↓default: + print('Some other number') +} +``` + +```swift +let a = switch i { + ↓case 1: 1 + ↓default: 2 +} +``` + +```swift +switch someBool { +case true: + print('red') + ↓case false: + print('blue') +} +``` + +```swift +if aBool { + switch someBool { + ↓case true: + print('red') + case false: + print('blue') + } +} +``` + +```swift +let a = switch i { +case 1: 1 + ↓default: 2 +} +``` + +```swift +switch i { ↓case .x: 1 ↓default: 0 } +``` + +```swift +// +// ignore_one_liners: true +// + +switch i { +↓case .x: 1 ↓default: 0 } + +``` + +```swift +// +// ignore_one_liners: true +// + +switch i { ↓case .x: 1 ↓default: 0 +} + +``` + +```swift +// +// ignore_one_liners: true +// + +switch i +{ ↓case .x: 1 ↓default: 0 } + +``` + +```swift +// +// ignore_one_liners: true +// + +let a = switch i { +case .x: 1 ↓default: 0 +} + +``` + +```swift +// +// ignore_one_liners: true +// + +let a = switch i { +↓case .x: 1 ↓default: 0 } + +``` \ No newline at end of file diff --git a/docs/description/switch_case_on_newline.md b/docs/description/switch_case_on_newline.md new file mode 100644 index 0000000..3cc2168 --- /dev/null +++ b/docs/description/switch_case_on_newline.md @@ -0,0 +1,198 @@ +# Cases on Newline + +Cases inside a switch should always be on a newline + +* **Identifier:** `switch_case_on_newline` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +/*case 1: */return true +``` + +```swift +//case 1: + return true +``` + +```swift +let x = [caseKey: value] +``` + +```swift +let x = [key: .default] +``` + +```swift +if case let .someEnum(value) = aFunction([key: 2]) { } +``` + +```swift +guard case let .someEnum(value) = aFunction([key: 2]) { } +``` + +```swift +for case let .someEnum(value) = aFunction([key: 2]) { } +``` + +```swift +enum Environment { + case development +} +``` + +```swift +enum Environment { + case development(url: URL) +} +``` + +```swift +enum Environment { + case development(url: URL) // staging +} +``` + +```swift +switch foo { + case 1: + return true +} +``` + +```swift +switch foo { + default: + return true +} +``` + +```swift +switch foo { + case let value: + return true +} +``` + +```swift +switch foo { + case .myCase: // error from network + return true +} +``` + +```swift +switch foo { + case let .myCase(value) where value > 10: + return false +} +``` + +```swift +switch foo { + case let .myCase(value) + where value > 10: + return false +} +``` + +```swift +switch foo { + case let .myCase(code: lhsErrorCode, description: _) + where lhsErrorCode > 10: +return false +} +``` + +```swift +switch foo { + case #selector(aFunction(_:)): + return false +} +``` + +```swift +do { + let loadedToken = try tokenManager.decodeToken(from: response) + return loadedToken +} catch { throw error } +``` + +## Triggering Examples + +```swift +switch foo { + ↓case 1: return true +} +``` + +```swift +switch foo { + ↓case let value: return true +} +``` + +```swift +switch foo { + ↓default: return true +} +``` + +```swift +switch foo { + ↓case "a string": return false +} +``` + +```swift +switch foo { + ↓case .myCase: return false // error from network +} +``` + +```swift +switch foo { + ↓case let .myCase(value) where value > 10: return false +} +``` + +```swift +switch foo { + ↓case #selector(aFunction(_:)): return false +} +``` + +```swift +switch foo { + ↓case let .myCase(value) + where value > 10: return false +} +``` + +```swift +switch foo { + ↓case .first, + .second: return false +} +``` \ No newline at end of file diff --git a/docs/description/syntactic_sugar.md b/docs/description/syntactic_sugar.md new file mode 100644 index 0000000..ab63954 --- /dev/null +++ b/docs/description/syntactic_sugar.md @@ -0,0 +1,184 @@ +# Syntactic Sugar + +Shorthand syntactic sugar should be used, i.e. [Int] instead of Array. + +* **Identifier:** `syntactic_sugar` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let x: [Int] +``` + +```swift +let x: [Int: String] +``` + +```swift +let x: Int? +``` + +```swift +func x(a: [Int], b: Int) -> [Int: Any] +``` + +```swift +let x: Int! +``` + +```swift +extension Array { + func x() { } +} +``` + +```swift +extension Dictionary { + func x() { } +} +``` + +```swift +let x: CustomArray +``` + +```swift +var currentIndex: Array.Index? +``` + +```swift +func x(a: [Int], b: Int) -> Array.Index +``` + +```swift +unsafeBitCast(nonOptionalT, to: Optional.self) +``` + +```swift +unsafeBitCast(someType, to: Swift.Array.self) +``` + +```swift +IndexingIterator>>.self +``` + +```swift +let y = Optional.Type +``` + +```swift +type is Optional.Type +``` + +```swift +let x: Foo.Optional +``` + +```swift +let x = case Optional.none = obj +``` + +```swift +let a = Swift.Optional.none +``` + +## Triggering Examples + +```swift +let x: ↓Array +``` + +```swift +let x: ↓Dictionary +``` + +```swift +let x: ↓Optional +``` + +```swift +let x: ↓Swift.Array +``` + +```swift +func x(a: ↓Array, b: Int) -> [Int: Any] +``` + +```swift +func x(a: ↓Swift.Array, b: Int) -> [Int: Any] +``` + +```swift +func x(a: [Int], b: Int) -> ↓Dictionary +``` + +```swift +let x = y as? ↓Array<[String: Any]> +``` + +```swift +let x = Box>() +``` + +```swift +func x() -> Box<↓Array> +``` + +```swift +func x() -> ↓Dictionary? +``` + +```swift +typealias Document = ↓Dictionary +``` + +```swift +func x(_ y: inout ↓Array) +``` + +```swift +let x:↓Dictionary> +``` + +```swift +func x() -> Any { return ↓Dictionary()} +``` + +```swift +let x = ↓Array.array(of: object) +``` + +```swift +let x = ↓Swift.Array.array(of: object) +``` + +```swift +@_specialize(where S == ↓Array) +public init(_ elements: S) +``` + +```swift +let dict: [String: Any] = [:] +_ = dict["key"] as? ↓Optional ?? Optional.none +``` \ No newline at end of file diff --git a/docs/description/test_case_accessibility.md b/docs/description/test_case_accessibility.md new file mode 100644 index 0000000..f9a8729 --- /dev/null +++ b/docs/description/test_case_accessibility.md @@ -0,0 +1,155 @@ +# Test Case Accessibility + +Test cases should only contain private non-test members + +* **Identifier:** `test_case_accessibility` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ allowed_prefixes + + [] +
+ test_parent_classes + + ["QuickSpec", "XCTestCase"] +
+ +## Non Triggering Examples + +```swift +let foo: String? +``` + +```swift +let foo: String? + +class FooTests: XCTestCase { + static let allTests: [String] = [] + + private let foo: String { + let nestedMember = "hi" + return nestedMember + } + + override static func setUp() {} + + override func setUp() {} + + override func setUpWithError() throws {} + + override static func tearDown() {} + + override func tearDown() {} + + override func tearDownWithError() {} + + override func someFutureXCTestFunction() { + super.someFutureXCTestFunction() + } + + func testFoo() { + XCTAssertTrue(true) + } + + func testBar() { + func nestedFunc() {} + } + + private someFunc(hasParam: Bool) {} +} +``` + +```swift +class FooTests: XCTestCase { + private struct MockSomething: Something {} +} +``` + +```swift +class FooTests: XCTestCase { + override init() { + super.init() + let foo = 1 + var bar = 2 + } +} +``` + +```swift +// +// allowed_prefixes: ["allowedPrefix"] +// + +class FooTests: XCTestCase { + func allowedPrefixTestFoo() {} +} + +``` + +```swift +class Foobar { + func setUp() {} + + func tearDown() {} + + func testFoo() {} +} +``` + +## Triggering Examples + +```swift +class FooTests: XCTestCase { + ↓typealias Bar = Foo.Bar + + ↓var foo: String? + ↓let bar: String? + + ↓static func foo() {} + + ↓func setUp(withParam: String) {} + + ↓func foobar() {} + + ↓func not_testBar() {} + + ↓enum Nested {} + + ↓static func testFoo() {} + + ↓static func allTests() {} + + ↓func testFoo(hasParam: Bool) {} +} + +final class BarTests: XCTestCase { + ↓class Nested {} +} +``` \ No newline at end of file diff --git a/docs/description/todo.md b/docs/description/todo.md new file mode 100644 index 0000000..94b930f --- /dev/null +++ b/docs/description/todo.md @@ -0,0 +1,78 @@ +# Todo + +TODOs and FIXMEs should be resolved. + +* **Identifier:** `todo` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ only + + [TODO, FIXME] +
+ +## Non Triggering Examples + +```swift +// notaTODO: +``` + +```swift +// notaFIXME: +``` + +## Triggering Examples + +```swift +// ↓TODO: +``` + +```swift +// ↓FIXME: +``` + +```swift +// ↓TODO(note) +``` + +```swift +// ↓FIXME(note) +``` + +```swift +/* ↓FIXME: */ +``` + +```swift +/* ↓TODO: */ +``` + +```swift +/** ↓FIXME: */ +``` + +```swift +/** ↓TODO: */ +``` \ No newline at end of file diff --git a/docs/description/toggle_bool.md b/docs/description/toggle_bool.md new file mode 100644 index 0000000..1ee865b --- /dev/null +++ b/docs/description/toggle_bool.md @@ -0,0 +1,66 @@ +# Toggle Bool + +Prefer `someBool.toggle()` over `someBool = !someBool` + +* **Identifier:** `toggle_bool` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +isHidden.toggle() +``` + +```swift +view.clipsToBounds.toggle() +``` + +```swift +func foo() { abc.toggle() } +``` + +```swift +view.clipsToBounds = !clipsToBounds +``` + +```swift +disconnected = !connected +``` + +```swift +result = !result.toggle() +``` + +## Triggering Examples + +```swift +↓isHidden = !isHidden +``` + +```swift +↓view.clipsToBounds = !view.clipsToBounds +``` + +```swift +func foo() { ↓abc = !abc } +``` \ No newline at end of file diff --git a/docs/description/trailing_closure.md b/docs/description/trailing_closure.md new file mode 100644 index 0000000..ce0f40b --- /dev/null +++ b/docs/description/trailing_closure.md @@ -0,0 +1,130 @@ +# Trailing Closure + +Trailing closure syntax should be used whenever possible + +* **Identifier:** `trailing_closure` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ only_single_muted_parameter + + false +
+ +## Non Triggering Examples + +```swift +foo.map { $0 + 1 } +``` + +```swift +foo.bar() +``` + +```swift +foo.reduce(0) { $0 + 1 } +``` + +```swift +if let foo = bar.map({ $0 + 1 }) { } +``` + +```swift +foo.something(param1: { $0 }, param2: { $0 + 1 }) +``` + +```swift +offsets.sorted { $0.offset < $1.offset } +``` + +```swift +foo.something({ return 1 }()) +``` + +```swift +foo.something({ return $0 }(1)) +``` + +```swift +foo.something(0, { return 1 }()) +``` + +```swift +for x in list.filter({ $0.isValid }) {} +``` + +```swift +if list.allSatisfy({ $0.isValid }) {} +``` + +```swift +foo(param1: 1, param2: { _ in true }, param3: 0) +``` + +```swift +foo(param1: 1, param2: { _ in true }) { $0 + 1 } +``` + +```swift +foo(param1: { _ in false }, param2: { _ in true }) +``` + +```swift +foo(param1: { _ in false }, param2: { _ in true }, param3: { _ in false }) +``` + +```swift +if f({ true }), g({ true }) { + print("Hello") +} +``` + +```swift +for i in h({ [1,2,3] }) { + print(i) +} +``` + +## Triggering Examples + +```swift +foo.map(↓{ $0 + 1 }) +``` + +```swift +foo.reduce(0, combine: ↓{ $0 + 1 }) +``` + +```swift +offsets.sorted(by: ↓{ $0.offset < $1.offset }) +``` + +```swift +foo.something(0, ↓{ $0 + 1 }) +``` + +```swift +foo.something(param1: { _ in true }, param2: 0, param3: ↓{ _ in false }) +``` \ No newline at end of file diff --git a/docs/description/trailing_comma.md b/docs/description/trailing_comma.md new file mode 100644 index 0000000..40815d0 --- /dev/null +++ b/docs/description/trailing_comma.md @@ -0,0 +1,124 @@ +# Trailing Comma + +Trailing commas in arrays and dictionaries should be avoided/enforced. + +* **Identifier:** `trailing_comma` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ mandatory_comma + + false +
+ +## Non Triggering Examples + +```swift +let foo = [1, 2, 3] +``` + +```swift +let foo = [] +``` + +```swift +let foo = [:] +``` + +```swift +let foo = [1: 2, 2: 3] +``` + +```swift +let foo = [Void]() +``` + +```swift +let example = [ 1, + 2 + // 3, +] +``` + +```swift +foo([1: "\(error)"]) +``` + +```swift +let foo = [Int]() +``` + +## Triggering Examples + +```swift +let foo = [1, 2, 3↓,] +``` + +```swift +let foo = [1, 2, 3↓, ] +``` + +```swift +let foo = [1, 2, 3 ↓,] +``` + +```swift +let foo = [1: 2, 2: 3↓, ] +``` + +```swift +struct Bar { + let foo = [1: 2, 2: 3↓, ] +} +``` + +```swift +let foo = [1, 2, 3↓,] + [4, 5, 6↓,] +``` + +```swift +let example = [ 1, +2↓, + // 3, +] +``` + +```swift +let foo = ["אבג", "αβγ", "🇺🇸"↓,] +``` + +```swift +class C { + #if true + func f() { + let foo = [1, 2, 3↓,] + } + #endif +} +``` + +```swift +foo([1: "\(error)"↓,]) +``` \ No newline at end of file diff --git a/docs/description/trailing_newline.md b/docs/description/trailing_newline.md new file mode 100644 index 0000000..d3916bf --- /dev/null +++ b/docs/description/trailing_newline.md @@ -0,0 +1,45 @@ +# Trailing Newline + +Files should have a single trailing newline + +* **Identifier:** `trailing_newline` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let a = 0 + +``` + +## Triggering Examples + +```swift +let a = 0 +``` + +```swift +let a = 0 + + +``` \ No newline at end of file diff --git a/docs/description/trailing_semicolon.md b/docs/description/trailing_semicolon.md new file mode 100644 index 0000000..d16f2b2 --- /dev/null +++ b/docs/description/trailing_semicolon.md @@ -0,0 +1,53 @@ +# Trailing Semicolon + +Lines should not have trailing semicolons + +* **Identifier:** `trailing_semicolon` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let a = 0 +``` + +```swift +let a = 0; let b = 0 +``` + +## Triggering Examples + +```swift +let a = 0↓; + +``` + +```swift +let a = 0↓; +let b = 1 +``` + +```swift +let a = 0↓; // a comment + +``` \ No newline at end of file diff --git a/docs/description/trailing_whitespace.md b/docs/description/trailing_whitespace.md new file mode 100644 index 0000000..a7609aa --- /dev/null +++ b/docs/description/trailing_whitespace.md @@ -0,0 +1,81 @@ +# Trailing Whitespace + +Lines should not have trailing whitespace + +* **Identifier:** `trailing_whitespace` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ ignores_empty_lines + + false +
+ ignores_comments + + true +
+ +## Non Triggering Examples + +```swift +let name: String + +``` + +```swift +// + +``` + +```swift +// + +``` + +```swift +let name: String // + +``` + +```swift +let name: String // + +``` + +## Triggering Examples + +```swift +let name: String + +``` + +```swift +/* */ let name: String + +``` \ No newline at end of file diff --git a/docs/description/type_body_length.md b/docs/description/type_body_length.md new file mode 100644 index 0000000..8eaa47d --- /dev/null +++ b/docs/description/type_body_length.md @@ -0,0 +1,5174 @@ +# Type Body Length + +Type bodies should not span too many lines + +* **Identifier:** `type_body_length` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** metrics +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ warning + + 250 +
+ error + + 350 +
+ +## Non Triggering Examples + +```swift +class Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` + +```swift +class Abc { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +``` + +```swift +class Abc { +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +} + +``` + +```swift +class Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 + +/* this is +a multiline comment +*/} + +``` + +```swift +struct Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` + +```swift +struct Abc { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +``` + +```swift +struct Abc { +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +} + +``` + +```swift +struct Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 + +/* this is +a multiline comment +*/} + +``` + +```swift +enum Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` + +```swift +enum Abc { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +``` + +```swift +enum Abc { +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +} + +``` + +```swift +enum Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 + +/* this is +a multiline comment +*/} + +``` + +```swift +actor Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` + +```swift +actor Abc { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +``` + +```swift +actor Abc { +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +// this is a comment +} + +``` + +```swift +actor Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 + +/* this is +a multiline comment +*/} + +``` + +## Triggering Examples + +```swift +↓class Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` + +```swift +↓struct Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` + +```swift +↓enum Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` + +```swift +↓actor Abc { +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +let abc = 0 +} + +``` \ No newline at end of file diff --git a/docs/description/type_contents_order.md b/docs/description/type_contents_order.md new file mode 100644 index 0000000..0d59075 --- /dev/null +++ b/docs/description/type_contents_order.md @@ -0,0 +1,324 @@ +# Type Contents Order + +Specifies the order of subtypes, properties, methods & more within a type. + +* **Identifier:** `type_contents_order` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ order + + [[case], [type_alias, associated_type], [subtype], [type_property], [instance_property], [ib_inspectable], [ib_outlet], [initializer], [type_method], [view_life_cycle_method], [ib_action, ib_segue_action], [other_method], [subscript], [deinitializer]] +
+ +## Non Triggering Examples + +```swift +class TestViewController: UIViewController { +// Type Aliases +typealias CompletionHandler = ((TestEnum) -> Void) + +// Subtypes +class TestClass { + // 10 lines +} + +struct TestStruct { + // 3 lines +} + +enum TestEnum { + // 5 lines +} + +// Type Properties +static let cellIdentifier: String = "AmazingCell" + +// Instance Properties +var shouldLayoutView1: Bool! +weak var delegate: TestViewControllerDelegate? +private var hasLayoutedView1: Bool = false +private var hasLayoutedView2: Bool = false + +private var hasAnyLayoutedView: Bool { + return hasLayoutedView1 || hasLayoutedView2 +} + +// IBOutlets +@IBOutlet private var view1: UIView! +@IBOutlet private var view2: UIView! + +// Initializers +override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) +} + +required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") +} + +// Type Methods +static func makeViewController() -> TestViewController { + // some code +} + +// View Life-Cycle Methods +override func viewDidLoad() { + super.viewDidLoad() + + view1.setNeedsLayout() + view1.layoutIfNeeded() + hasLayoutedView1 = true +} + +override func willMove(toParent parent: UIViewController?) { + super.willMove(toParent: parent) + if parent == nil { + viewModel.willMoveToParent() + } +} + +override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + view2.setNeedsLayout() + view2.layoutIfNeeded() + hasLayoutedView2 = true +} + +override func viewIsAppearing(_ animated: Bool) { + super.viewIsAppearing(animated) +} + +// IBActions +@IBAction func goNextButtonPressed() { + goToNextVc() + delegate?.didPressTrackedButton() +} + +// Other Methods +func goToNextVc() { /* TODO */ } + +func goToInfoVc() { /* TODO */ } + +func goToRandomVc() { + let viewCtrl = getRandomVc() + present(viewCtrl, animated: true) +} + +private func getRandomVc() -> UIViewController { return UIViewController() } + +// Subscripts +subscript(_ someIndexThatIsNotEvenUsed: Int) -> String { + get { + return "This is just a test" + } + + set { + log.warning("Just a test", newValue) + } +} + +deinit { + log.debug("deinit") +}, +} +``` + +```swift +struct ContentView: View { + @available(SwiftUI_v5, *) // Availability macro syntax: https://github.com/swiftlang/swift/pull/65218 + var v5Body: some View { EmptyView() } + var body: some View { EmptyView() } +} +``` + +## Triggering Examples + +```swift +class TestViewController: UIViewController { + // Subtypes + ↓class TestClass { + // 10 lines + } + + // Type Aliases + typealias CompletionHandler = ((TestEnum) -> Void) +} +``` + +```swift +class TestViewController: UIViewController { + // Stored Type Properties + ↓static let cellIdentifier: String = "AmazingCell" + + // Subtypes + class TestClass { + // 10 lines + } +} +``` + +```swift +class TestViewController: UIViewController { + // Stored Instance Properties + ↓var shouldLayoutView1: Bool! + + // Stored Type Properties + static let cellIdentifier: String = "AmazingCell" +} +``` + +```swift +class TestViewController: UIViewController { + // IBOutlets + @IBOutlet private ↓var view1: UIView! + + // Computed Instance Properties + private var hasAnyLayoutedView: Bool { + return hasLayoutedView1 || hasLayoutedView2 + } +} +``` + +```swift +class TestViewController: UIViewController { + + // deinitializer + ↓deinit { + log.debug("deinit") + } + + // Initializers + override ↓init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + // IBOutlets + @IBOutlet private var view1: UIView! + @IBOutlet private var view2: UIView! +} +``` + +```swift +class TestViewController: UIViewController { + // View Life-Cycle Methods + override ↓func viewDidLoad() { + super.viewDidLoad() + + view1.setNeedsLayout() + view1.layoutIfNeeded() + hasLayoutedView1 = true + } + + // Type Methods + static func makeViewController() -> TestViewController { + // some code + } +} +``` + +```swift +class TestViewController: UIViewController { + // IBActions + @IBAction ↓func goNextButtonPressed() { + goToNextVc() + delegate?.didPressTrackedButton() + } + + // View Life-Cycle Methods + override func viewDidLoad() { + super.viewDidLoad() + + view1.setNeedsLayout() + view1.layoutIfNeeded() + hasLayoutedView1 = true + } +} +``` + +```swift +class TestViewController: UIViewController { + // Other Methods + ↓func goToNextVc() { /* TODO */ } + + // IBActions + @IBAction func goNextButtonPressed() { + goToNextVc() + delegate?.didPressTrackedButton() + } +} +``` + +```swift +class TestViewController: UIViewController { + // Subscripts + ↓subscript(_ someIndexThatIsNotEvenUsed: Int) -> String { + get { + return "This is just a test" + } + + set { + log.warning("Just a test", newValue) + } + } + + // MARK: Other Methods + func goToNextVc() { /* TODO */ } +} +``` + +```swift +final class C { + ↓var i = 1 + static var I = 2 + class var s: Int { + struct S {} + return 3 + } +} +``` + +```swift +final class C { + ↓var i = 1 + #if os(macOS) + static var I = 2 + #endif +} +``` + +```swift +struct S { + ↓var i = 1 + #if os(macOS) + #if swift(>=5.3) + ↓func f() {} + #endif + #else + static var i = 3 + #endif +} +``` \ No newline at end of file diff --git a/docs/description/type_name.md b/docs/description/type_name.md new file mode 100644 index 0000000..c4eefdd --- /dev/null +++ b/docs/description/type_name.md @@ -0,0 +1,244 @@ +# Type Name + +Type name should only contain alphanumeric characters, start with an uppercase character and span between 3 and 40 characters in length. +Private types may start with an underscore. + +* **Identifier:** `type_name` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ min_length + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 3 +
+ error + + 0 +
+
+ max_length + + + + + + + + + + + + + + + +
KeyValue
+ warning + + 40 +
+ error + + 1000 +
+
+ excluded + + [] +
+ allowed_symbols + + [] +
+ unallowed_symbols_severity + + error +
+ validates_start_with_lowercase + + error +
+ validate_protocols + + true +
+ +## Non Triggering Examples + +```swift +class MyType {} +``` + +```swift +private struct _MyType {} +``` + +```swift +enum AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} +``` + +```swift +typealias Foo = Void +``` + +```swift +private typealias Foo = Void +``` + +```swift +protocol Foo { + associatedtype Bar +} +``` + +```swift +protocol Foo { + associatedtype Bar: Equatable +} +``` + +```swift +enum MyType { +case value +} +``` + +```swift +// +// validate_protocols: false +// + +protocol P {} + +``` + +```swift +struct SomeStruct { + enum `Type` { + case x, y, z + } +} +``` + +## Triggering Examples + +```swift +class ↓myType {} +``` + +```swift +enum ↓_MyType {} +``` + +```swift +private struct ↓MyType_ {} +``` + +```swift +struct ↓My {} +``` + +```swift +struct ↓AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} +``` + +```swift +class ↓MyView_Previews +``` + +```swift +private struct ↓_MyView_Previews +``` + +```swift +typealias ↓X = Void +``` + +```swift +private typealias ↓Foo_Bar = Void +``` + +```swift +private typealias ↓foo = Void +``` + +```swift +typealias ↓AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = Void +``` + +```swift +protocol Foo { + associatedtype ↓X +} +``` + +```swift +protocol Foo { + associatedtype ↓Foo_Bar: Equatable +} +``` + +```swift +protocol Foo { + associatedtype ↓AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} +``` + +```swift +protocol ↓X {} +``` \ No newline at end of file diff --git a/docs/description/typesafe_array_init.md b/docs/description/typesafe_array_init.md new file mode 100644 index 0000000..816b822 --- /dev/null +++ b/docs/description/typesafe_array_init.md @@ -0,0 +1,70 @@ +# Type-safe Array Init + +Prefer using `Array(seq)` over `seq.map { $0 }` to convert a sequence into an Array + +* **Identifier:** `typesafe_array_init` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** Yes +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +enum MyError: Error {} +let myResult: Result = .success("") +let result: Result = myResult.map { $0 } +``` + +```swift +struct IntArray { + let elements = [1, 2, 3] + func map(_ transformer: (Int) throws -> T) rethrows -> [T] { + try elements.map(transformer) + } +} +let ints = IntArray() +let intsCopy = ints.map { $0 } +``` + +## Triggering Examples + +```swift +func f(s: Seq) -> [Seq.Element] { + s.↓map({ $0 }) +} +``` + +```swift +func f(array: [Int]) -> [Int] { + array.↓map { $0 } +} +``` + +```swift +let myInts = [1, 2, 3].↓map { return $0 } +``` + +```swift +struct Generator: Sequence, IteratorProtocol { + func next() -> Int? { nil } +} +let array = Generator().↓map { i in i } +``` \ No newline at end of file diff --git a/docs/description/unavailable_condition.md b/docs/description/unavailable_condition.md new file mode 100644 index 0000000..6f2825e --- /dev/null +++ b/docs/description/unavailable_condition.md @@ -0,0 +1,82 @@ +# Unavailable Condition + +Use #unavailable/#available instead of #available/#unavailable with an empty body. + +* **Identifier:** `unavailable_condition` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.6.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +if #unavailable(iOS 13) { + loadMainWindow() +} +``` + +```swift +if #available(iOS 9.0, *) { + doSomething() +} else { + legacyDoSomething() +} +``` + +```swift +if #available(macOS 11.0, *) { + // Do nothing +} else if #available(macOS 10.15, *) { + print("do some stuff") +} +``` + +## Triggering Examples + +```swift +if ↓#available(iOS 14.0) { + +} else { + oldIos13TrackingLogic(isEnabled: ASIdentifierManager.shared().isAdvertisingTrackingEnabled) +} +``` + +```swift +if ↓#available(iOS 14.0) { + // we don't need to do anything here +} else { + oldIos13TrackingLogic(isEnabled: ASIdentifierManager.shared().isAdvertisingTrackingEnabled) +} +``` + +```swift +if ↓#available(iOS 13, *) {} else { + loadMainWindow() +} +``` + +```swift +if ↓#unavailable(iOS 13) { + // Do nothing +} else if i < 2 { + loadMainWindow() +} +``` \ No newline at end of file diff --git a/docs/description/unavailable_function.md b/docs/description/unavailable_function.md new file mode 100644 index 0000000..33b15e7 --- /dev/null +++ b/docs/description/unavailable_function.md @@ -0,0 +1,93 @@ +# Unavailable Function + +Unimplemented functions should be marked as unavailable + +* **Identifier:** `unavailable_function` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class ViewController: UIViewController { + @available(*, unavailable) + public required init?(coder aDecoder: NSCoder) { + preconditionFailure("init(coder:) has not been implemented") + } +} +``` + +```swift +func jsonValue(_ jsonString: String) -> NSObject { + let data = jsonString.data(using: .utf8)! + let result = try! JSONSerialization.jsonObject(with: data, options: []) + if let dict = (result as? [String: Any])?.bridge() { + return dict + } else if let array = (result as? [Any])?.bridge() { + return array + } + fatalError() +} +``` + +```swift +func resetOnboardingStateAndCrash() -> Never { + resetUserDefaults() + // Crash the app to re-start the onboarding flow. + fatalError("Onboarding re-start crash.") +} +``` + +## Triggering Examples + +```swift +class ViewController: UIViewController { + public required ↓init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} +``` + +```swift +class ViewController: UIViewController { + public required ↓init?(coder aDecoder: NSCoder) { + let reason = "init(coder:) has not been implemented" + fatalError(reason) + } +} +``` + +```swift +class ViewController: UIViewController { + public required ↓init?(coder aDecoder: NSCoder) { + preconditionFailure("init(coder:) has not been implemented") + } +} +``` + +```swift +↓func resetOnboardingStateAndCrash() { + resetUserDefaults() + // Crash the app to re-start the onboarding flow. + fatalError("Onboarding re-start crash.") +} +``` \ No newline at end of file diff --git a/docs/description/unhandled_throwing_task.md b/docs/description/unhandled_throwing_task.md new file mode 100644 index 0000000..30054b1 --- /dev/null +++ b/docs/description/unhandled_throwing_task.md @@ -0,0 +1,220 @@ +# Unhandled Throwing Task + +Errors thrown inside this task are not handled, which may be unexpected. Handle errors inside the task, or use `try await` to access the Tasks value and handle errors. See this forum thread for more details: https://forums.swift.org/t/task-initializer-with-throwing-closure-swallows-error/56066 + +* **Identifier:** `unhandled_throwing_task` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + error +
+ +## Non Triggering Examples + +```swift +Task { + try await myThrowingFunction() +} +``` + +```swift +Task { + try? await myThrowingFunction() +} +``` + +```swift +Task { + try! await myThrowingFunction() +} +``` + +```swift +Task { + let text = try myThrowingFunction() + return text +} +``` + +```swift +Task { + do { + try myThrowingFunction() + } catch let e { + print(e) + } +} +``` + +```swift +func someFunction() throws { + Task { + anotherFunction() + do { + try myThrowingFunction() + } catch { + print(error) + } + } + + try something() +} +``` + +```swift +let task = Task { + try await myThrowingFunction() +} +``` + +```swift +var task = Task { + try await myThrowingFunction() +} +``` + +```swift +try await Task { + try await myThrowingFunction() +}.value +``` + +```swift +executor.task = Task { + try await isolatedOpen(.init(executor.asUnownedSerialExecutor())) +} +``` + +```swift +let result = await Task { + throw CancellationError() +}.result +``` + +```swift +func makeTask() -> Task { + return Task { + try await someThrowingFunction() + } +} +``` + +```swift +func makeTask() -> Task { + // Implicit return + Task { + try await someThrowingFunction() + } +} +``` + +```swift +Task { + return Result { + try someThrowingFunc() + } +} +``` + +## Triggering Examples + +```swift +↓Task { + try await myThrowingFunction() +} +``` + +```swift +↓Task { + let text = try myThrowingFunction() + return text +} +``` + +```swift +↓Task { + do { + try myThrowingFunction() + } +} +``` + +```swift +↓Task { + do { + try myThrowingFunction() + } catch let e as FooError { + print(e) + } +} +``` + +```swift +↓Task { + do { + throw FooError.bar + } +} +``` + +```swift +↓Task { + throw FooError.bar +} +``` + +```swift +↓Task<_, _> { + throw FooError.bar +} +``` + +```swift +↓Task { + throw FooError.bar +} +``` + +```swift +↓Task { + do { + try foo() + } catch { + try bar() + } +} +``` + +```swift +↓Task { + do { + try foo() + } catch { + throw BarError() + } +} +``` + +```swift +func doTask() { + ↓Task { + try await someThrowingFunction() + } +} +``` \ No newline at end of file diff --git a/docs/description/unneeded_break_in_switch.md b/docs/description/unneeded_break_in_switch.md new file mode 100644 index 0000000..e5628f2 --- /dev/null +++ b/docs/description/unneeded_break_in_switch.md @@ -0,0 +1,111 @@ +# Unneeded Break in Switch + +Avoid using unneeded break statements + +* **Identifier:** `unneeded_break_in_switch` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +switch foo { +case .bar: + break +} +``` + +```swift +switch foo { +default: + break +} +``` + +```swift +switch foo { +case .bar: + for i in [0, 1, 2] { break } +} +``` + +```swift +switch foo { +case .bar: + if true { break } +} +``` + +```swift +switch foo { +case .bar: + something() +} +``` + +```swift +let items = [Int]() +for item in items { + if bar() { + do { + try foo() + } catch { + bar() + break + } + } +} +``` + +## Triggering Examples + +```swift +switch foo { +case .bar: + something() + ↓break +} +``` + +```swift +switch foo { +case .bar: + something() + ↓break // comment +} +``` + +```swift +switch foo { +default: + something() + ↓break +} +``` + +```swift +switch foo { +case .foo, .foo2 where condition: + something() + ↓break +} +``` \ No newline at end of file diff --git a/docs/description/unneeded_override.md b/docs/description/unneeded_override.md new file mode 100644 index 0000000..f682e59 --- /dev/null +++ b/docs/description/unneeded_override.md @@ -0,0 +1,270 @@ +# Unneeded Overridden Functions + +Remove overridden functions that don't do anything except call their super + +* **Identifier:** `unneeded_override` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ affect_initializers + + false +
+ excluded_methods + + [] +
+ +## Non Triggering Examples + +```swift +class Foo { + override func bar() { + super.bar() + print("hi") + } +} +``` + +```swift +class Foo { + @available(*, unavailable) + override func bar() { + super.bar() + } +} +``` + +```swift +class Foo { + @objc override func bar() { + super.bar() + } +} +``` + +```swift +class Foo { + override func bar() { + super.bar() + super.bar() + } +} +``` + +```swift +class Foo { + override func bar() throws { + // Doing a different variation of 'try' changes behavior + try! super.bar() + } +} +``` + +```swift +class Foo { + override func bar() throws { + // Doing a different variation of 'try' changes behavior + try? super.bar() + } +} +``` + +```swift +class Foo { + override func bar() async throws { + // Doing a different variation of 'try' changes behavior + await try! super.bar() + } +} +``` + +```swift +class Foo { + override func bar(arg: Bool) { + // Flipping the argument changes behavior + super.bar(arg: !arg) + } +} +``` + +```swift +class Foo { + override func bar(_ arg: Int) { + // Changing the argument changes behavior + super.bar(arg + 1) + } +} +``` + +```swift +class Foo { + override func bar(arg: Int) { + // Changing the argument changes behavior + super.bar(arg: arg.var) + } +} +``` + +```swift +class Foo { + override func bar(_ arg: Int) { + // Not passing arguments because they have default values changes behavior + super.bar() + } +} +``` + +```swift +class Foo { + override func bar(arg: Int, _ arg3: Bool) { + // Calling a super function with different argument labels changes behavior + super.bar(arg2: arg, arg3: arg3) + } +} +``` + +```swift +class Foo { + override func bar(animated: Bool, completion: () -> Void) { + super.bar(animated: animated) { + // This likely changes behavior + } + } +} +``` + +```swift +class Foo { + override func bar(animated: Bool, completion: () -> Void) { + super.bar(animated: animated, completion: { + // This likely changes behavior + }) + } +} +``` + +```swift +class Baz: Foo { + // A default argument might be a change + override func bar(value: String = "Hello") { + super.bar(value: value) + } +} +``` + +```swift +class C { + override func foo() { + super.foo {} + } + override func bar(_ c: () -> Void) { + super.bar {} + } + override func baz(_ c: () -> Void) { + super.baz({}) + } + override func qux(c: () -> Void) { + super.qux(c: {}) + } +} +``` + +```swift +// +// excluded_methods: ["setUp"] +// + +class FooTestCase: XCTestCase { + override func setUp() { + super.setUp() + } +} + +``` + +## Triggering Examples + +```swift +class Foo { + ↓override func bar() { + super.bar() + } +} +``` + +```swift +class Foo { + ↓override func bar() { + return super.bar() + } +} +``` + +```swift +class Foo { + ↓override func bar() { + super.bar() + // comments don't affect this + } +} +``` + +```swift +class Foo { + ↓override func bar() async { + await super.bar() + } +} +``` + +```swift +class Foo { + ↓override func bar() throws { + try super.bar() + // comments don't affect this + } +} +``` + +```swift +class Foo { + ↓override func bar(arg: Bool) throws { + try super.bar(arg: arg) + } +} +``` + +```swift +class Foo { + ↓override func bar(animated: Bool, completion: () -> Void) { + super.bar(animated: animated, completion: completion) + } +} +``` \ No newline at end of file diff --git a/docs/description/unneeded_parentheses_in_closure_argument.md b/docs/description/unneeded_parentheses_in_closure_argument.md new file mode 100644 index 0000000..e43c6d8 --- /dev/null +++ b/docs/description/unneeded_parentheses_in_closure_argument.md @@ -0,0 +1,98 @@ +# Unneeded Parentheses in Closure Argument + +Parentheses are not needed when declaring closure arguments + +* **Identifier:** `unneeded_parentheses_in_closure_argument` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let foo = { (bar: Int) in } +``` + +```swift +let foo = { bar, _ in } +``` + +```swift +let foo = { bar in } +``` + +```swift +let foo = { bar -> Bool in return true } +``` + +```swift +DispatchQueue.main.async { () -> Void in + doSomething() +} +``` + +## Triggering Examples + +```swift +call(arg: { ↓(bar) in }) +``` + +```swift +call(arg: { ↓(bar, _) in }) +``` + +```swift +let foo = { ↓(bar) -> Bool in return true } +``` + +```swift +foo.map { ($0, $0) }.forEach { ↓(x, y) in } +``` + +```swift +foo.bar { [weak self] ↓(x, y) in } +``` + +```swift +[].first { ↓(temp) in + [].first { ↓(temp) in + [].first { ↓(temp) in + _ = temp + return false + } + return false + } + return false +} +``` + +```swift +[].first { temp in + [].first { ↓(temp) in + [].first { ↓(temp) in + _ = temp + return false + } + return false + } + return false +} +``` \ No newline at end of file diff --git a/docs/description/unneeded_synthesized_initializer.md b/docs/description/unneeded_synthesized_initializer.md new file mode 100644 index 0000000..ace9ae7 --- /dev/null +++ b/docs/description/unneeded_synthesized_initializer.md @@ -0,0 +1,430 @@ +# Unneeded Synthesized Initializer + +Default or memberwise initializers that will be automatically synthesized do not need to be manually defined. + +* **Identifier:** `unneeded_synthesized_initializer` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +struct Foo { + let bar: String + + // Synthesized initializer would not be private. + private init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + var bar: String + + // Synthesized initializer would not be private. + private init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + let bar: String + + // Synthesized initializer would not be fileprivate. + fileprivate init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + let bar: String + + // Synthesized initializer would not prepend "foo". + init(bar: String) { + self.bar = "foo" + bar + } +} +``` + +```swift +internal struct Foo { + let bar: String + + // Failable initializer + init?(bar: String) { + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + let bar: String + + // Initializer throws + init(bar: String) throws { + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + let bar: String + + // Different argument labels + init(_ bar: String) { + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + var bar: String = "foo" + + // Different default values + init(bar: String = "bar") { + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + private static var bar: String + + // var is static + init(bar: String) { + Self.bar = bar + } +} +``` + +```swift +internal struct Foo { + private var bar: String + + // var is private + init(bar: String) { + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + fileprivate var bar: String + + // var is fileprivate + init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + var foo: String + var bar: String + + // init has no body + init(foo: String, bar: String) { + } +} +``` + +```swift +struct Foo { + var foo: String + var bar: String + + // foo is not initialized + init(foo: String, bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + var foo: String + var bar: String + + // Ordering of args is different from properties. + init(bar: String, foo: String) { + self.foo = foo + self.bar = bar + } +} +``` + +```swift +@frozen +public struct Field { + @usableFromInline + let index: Int + + @usableFromInline + let parent: Metadata + + @inlinable // inlinable + init(index: Int, parent: Metadata) { + self.index = index + self.parent = parent + } +} +``` + +```swift +internal struct Foo { + var bar: String = "" + var baz: Int = 0 + + // These initializers must be declared. + init() { } + + init(bar: String = "", baz: Int = 0) { + self.bar = bar + self.baz = baz + } + + // Because manually declared initializers block + // synthesization. + init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + init() { + print("perform side effect") + } +} +``` + +```swift +struct Foo { + var bar: Int = 0 + + init(bar: Int = 0) { + self.bar = bar + print("perform side effect") + } +} +``` + +```swift +struct Foo { + var bar: Int + + init(@Clamped bar: Int) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + let bar: Int + + init(bar: Int) { + self.bar = bar + } + init?() { + return nil + } +} +``` + +```swift +struct Foo { + @available(*, unavailable) + init() {} +} +``` + +## Triggering Examples + +```swift +struct Foo { + let bar: String + + ↓init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + var bar: String + + ↓init(bar: String) { + self.bar = bar + } +} +``` + +```swift +private struct Foo { + let bar: String + + ↓init(bar: String) { + self.bar = bar + } +} +``` + +```swift +fileprivate struct Foo { + let bar: String + + ↓init(bar: String) { + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + fileprivate var bar: String + + ↓fileprivate init(bar: String) { + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + private var bar: String + + ↓private init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + var foo: String + var bar: String + + ↓init(foo: String, bar: String) { + self.foo = foo + self.bar = bar + } +} +``` + +```swift +internal struct Foo { + var bar: String + + ↓internal init(bar: String) { + self.bar = bar + } +} +``` + +```swift +struct Foo { + var bar: String = "" + + ↓init() { + // Empty initializer will be generated automatically + // when all vars have default values. + } +} +``` + +```swift +struct Foo { + var bar: String = "" + + ↓init() { + // Empty initializer + } + + ↓init(bar: String = "") { + self.bar = bar + } +} +``` + +```swift +struct Foo { + var bar = "" + + ↓init(bar: String = "") { + self.bar = bar + } +} +``` + +```swift +struct Outer { + struct Inner { + let prop: Int + + ↓init(prop: Int) { + self.prop = prop + } + } +} +``` + +```swift +class Foo { + struct Bar { + let baz: Int + + ↓init(baz: Int) { + self.baz = baz + } + } +} +``` + +```swift +struct Foo { + let i: Int + struct Bar { + let j: Int + ↓init(j: Int) { + self.j = j + } + } + ↓init(i: Int) { + self.i = i + } +} +``` \ No newline at end of file diff --git a/docs/description/unowned_variable_capture.md b/docs/description/unowned_variable_capture.md new file mode 100644 index 0000000..a8e7051 --- /dev/null +++ b/docs/description/unowned_variable_capture.md @@ -0,0 +1,76 @@ +# Unowned Variable Capture + +Prefer capturing references as weak to avoid potential crashes + +* **Identifier:** `unowned_variable_capture` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +foo { [weak self] in _ } +``` + +```swift +foo { [weak self] param in _ } +``` + +```swift +foo { [weak bar] in _ } +``` + +```swift +foo { [weak bar] param in _ } +``` + +```swift +foo { bar in _ } +``` + +```swift +foo { $0 } +``` + +```swift +final class First {} +final class Second { + unowned var value: First + init(value: First) { + self.value = value + } +} +``` + +## Triggering Examples + +```swift +foo { [↓unowned self] in _ } +``` + +```swift +foo { [↓unowned bar] in _ } +``` + +```swift +foo { [bar, ↓unowned self] in _ } +``` \ No newline at end of file diff --git a/docs/description/untyped_error_in_catch.md b/docs/description/untyped_error_in_catch.md new file mode 100644 index 0000000..c2ae5af --- /dev/null +++ b/docs/description/untyped_error_in_catch.md @@ -0,0 +1,109 @@ +# Untyped Error in Catch + +Catch statements should not declare error variables without type casting + +* **Identifier:** `untyped_error_in_catch` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +do { + try foo() +} catch {} +``` + +```swift +do { + try foo() +} catch Error.invalidOperation { +} catch {} +``` + +```swift +do { + try foo() +} catch let error as MyError { +} catch {} +``` + +```swift +do { + try foo() +} catch var error as MyError { +} catch {} +``` + +```swift +do { + try something() +} catch let e where e.code == .fileError { + // can be ignored +} catch { + print(error) +} +``` + +## Triggering Examples + +```swift +do { + try foo() +} ↓catch var error {} +``` + +```swift +do { + try foo() +} ↓catch let error {} +``` + +```swift +do { + try foo() +} ↓catch let someError {} +``` + +```swift +do { + try foo() +} ↓catch var someError {} +``` + +```swift +do { + try foo() +} ↓catch let e {} +``` + +```swift +do { + try foo() +} ↓catch(let error) {} +``` + +```swift +do { + try foo() +} ↓catch (let error) {} +``` \ No newline at end of file diff --git a/docs/description/unused_capture_list.md b/docs/description/unused_capture_list.md new file mode 100644 index 0000000..56a09c2 --- /dev/null +++ b/docs/description/unused_capture_list.md @@ -0,0 +1,179 @@ +# Unused Capture List + +Unused reference in a capture list should be removed + +* **Identifier:** `unused_capture_list` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[1, 2].map { + [ weak + delegate, + unowned + self + ] num in + delegate.handle(num) +} +``` + +```swift +[1, 2].map { [weak self] num in + self?.handle(num) +} +``` + +```swift +let failure: Failure = { [weak self, unowned delegate = self.delegate!] foo in + delegate.handle(foo, self) +} +``` + +```swift +numbers.forEach({ + [weak handler] in + handler?.handle($0) +}) +``` + +```swift +withEnvironment(apiService: MockService(fetchProjectResponse: project)) { + [Device.phone4_7inch, Device.phone5_8inch, Device.pad].forEach { device in + device.handle() + } +} +``` + +```swift +{ [foo] _ in foo.bar() }() +``` + +```swift +sizes.max().flatMap { [(offset: offset, size: $0)] } ?? [] +``` + +```swift +[1, 2].map { [self] num in + handle(num) +} +``` + +```swift +[1, 2].map { [unowned self] num in + handle(num) +} +``` + +```swift +[1, 2].map { [self, unowned delegate = self.delegate!] num in + delegate.handle(num) +} +``` + +```swift +[1, 2].map { [unowned self, unowned delegate = self.delegate!] num in + delegate.handle(num) +} +``` + +```swift +[1, 2].map { + [ weak + delegate, + self + ] num in + delegate.handle(num) +} +``` + +```swift +rx.onViewDidAppear.subscribe(onNext: { [unowned self] in + doSomething() +}).disposed(by: disposeBag) +``` + +```swift +let closure = { [weak self] in + guard let self else { + return + } + someInstanceFunction() +} +``` + +## Triggering Examples + +```swift +[1, 2].map { [↓weak self] num in + print(num) +} +``` + +```swift +let failure: Failure = { [weak self, ↓unowned delegate = self.delegate!] foo in + self?.handle(foo) +} +``` + +```swift +let failure: Failure = { [↓weak self, ↓unowned delegate = self.delegate!] foo in + print(foo) +} +``` + +```swift +numbers.forEach({ + [weak handler] in + print($0) +}) +``` + +```swift +numbers.forEach({ + [self, ↓weak handler] in + print($0) +}) +``` + +```swift +withEnvironment(apiService: MockService(fetchProjectResponse: project)) { [↓foo] in + [Device.phone4_7inch, Device.phone5_8inch, Device.pad].forEach { device in + device.handle() + } +} +``` + +```swift +{ [↓foo] in _ }() +``` + +```swift +let closure = { [↓weak a] in + // The new `a` immediately shadows the captured `a` which thus isn't needed. + guard let a = getOptionalValue() else { + return + } + someInstanceFunction() +} +``` \ No newline at end of file diff --git a/docs/description/unused_closure_parameter.md b/docs/description/unused_closure_parameter.md new file mode 100644 index 0000000..481186b --- /dev/null +++ b/docs/description/unused_closure_parameter.md @@ -0,0 +1,211 @@ +# Unused Closure Parameter + +Unused parameter in a closure should be replaced with _ + +* **Identifier:** `unused_closure_parameter` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +[1, 2].map { $0 + 1 } +``` + +```swift +[1, 2].map({ $0 + 1 }) +``` + +```swift +[1, 2].map { number in + number + 1 +} +``` + +```swift +[1, 2].map { _ in + 3 +} +``` + +```swift +[1, 2].something { number, idx in + return number * idx +} +``` + +```swift +let isEmpty = [1, 2].isEmpty() +``` + +```swift +violations.sorted(by: { lhs, rhs in + return lhs.location > rhs.location +}) +``` + +```swift +rlmConfiguration.migrationBlock.map { rlmMigration in + return { migration, schemaVersion in + rlmMigration(migration.rlmMigration, schemaVersion) + } +} +``` + +```swift +genericsFunc { (a: Type, b) in + a + b +} +``` + +```swift +var label: UILabel = { (lbl: UILabel) -> UILabel in + lbl.backgroundColor = .red + return lbl +}(UILabel()) +``` + +```swift +hoge(arg: num) { num in + return num +} +``` + +```swift +({ (manager: FileManager) in + print(manager) +})(FileManager.default) +``` + +```swift +withPostSideEffect { input in + if true { print("\(input)") } +} +``` + +```swift +viewModel?.profileImage.didSet(weak: self) { (self, profileImage) in + self.profileImageView.image = profileImage +} +``` + +```swift +let failure: Failure = { task, error in + observer.sendFailed(error, task) +} +``` + +```swift +List($names) { $name in + Text(name) +} +``` + +```swift +List($names) { $name in + TextField($name) +} +``` + +```swift +_ = ["a"].filter { `class` in `class`.hasPrefix("a") } +``` + +```swift +let closure: (Int) -> Void = { `foo` in _ = foo } +``` + +```swift +let closure: (Int) -> Void = { foo in _ = `foo` } +``` + +## Triggering Examples + +```swift +[1, 2].map { ↓number in + return 3 } +``` + +```swift +[1, 2].map { ↓number in + return numberWithSuffix } +``` + +```swift +[1, 2].map { ↓number in + return 3 // number } +``` + +```swift +[1, 2].map { ↓number in + return 3 "number" } +``` + +```swift +[1, 2].something { number, ↓idx in + return number } +``` + +```swift +genericsFunc { (↓number: TypeA, idx: TypeB) in return idx } +``` + +```swift +let c: (Int) -> Void = { foo in _ = .foo } +``` + +```swift +hoge(arg: num) { ↓num in +} +``` + +```swift +fooFunc { ↓아 in } +``` + +```swift +func foo () { + bar { ↓number in return 3 } +``` + +```swift +viewModel?.profileImage.didSet(weak: self) { (↓self, profileImage) in + profileImageView.image = profileImage +} +``` + +```swift +let failure: Failure = { ↓task, error in + observer.sendFailed(error) +} +``` + +```swift +List($names) { ↓$name in + Text("Foo") +} +``` + +```swift +let class1 = "a" +_ = ["a"].filter { ↓`class` in `class1`.hasPrefix("a") } +``` \ No newline at end of file diff --git a/docs/description/unused_control_flow_label.md b/docs/description/unused_control_flow_label.md new file mode 100644 index 0000000..df0f3dd --- /dev/null +++ b/docs/description/unused_control_flow_label.md @@ -0,0 +1,99 @@ +# Unused Control Flow Label + +Unused control flow label should be removed + +* **Identifier:** `unused_control_flow_label` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +loop: while true { break loop } +``` + +```swift +loop: while true { continue loop } +``` + +```swift +loop: + while true { break loop } +``` + +```swift +while true { break } +``` + +```swift +loop: for x in array { break loop } +``` + +```swift +label: switch number { +case 1: print("1") +case 2: print("2") +default: break label +} +``` + +```swift +loop: repeat { + if x == 10 { + break loop + } +} while true +``` + +## Triggering Examples + +```swift +↓loop: while true { break } +``` + +```swift +↓loop: while true { break loop1 } +``` + +```swift +↓loop: while true { break outerLoop } +``` + +```swift +↓loop: for x in array { break } +``` + +```swift +↓label: switch number { +case 1: print("1") +case 2: print("2") +default: break +} +``` + +```swift +↓loop: repeat { + if x == 10 { + break + } +} while true +``` \ No newline at end of file diff --git a/docs/description/unused_declaration.md b/docs/description/unused_declaration.md new file mode 100644 index 0000000..9831960 --- /dev/null +++ b/docs/description/unused_declaration.md @@ -0,0 +1,283 @@ +# Unused Declaration + +Declarations should be referenced at least once within all files linted + +* **Identifier:** `unused_declaration` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** Yes +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + error +
+ include_public_and_open + + false +
+ related_usrs_to_skip + + ["s:7SwiftUI15PreviewProviderP"] +
+ +## Non Triggering Examples + +```swift +let kConstant = 0 +_ = kConstant +``` + +```swift +enum Change { + case insert(T) + case delete(T) +} + +extension Sequence { + func deletes() -> [T] where Element == Change { + return compactMap { operation in + if case .delete(let value) = operation { + return value + } else { + return nil + } + } + } +} + +let changes = [Change.insert(0), .delete(0)] +_ = changes.deletes() +``` + +```swift +struct Item: Codable {} +struct ResponseModel: Codable { + let items: [Item] + + enum CodingKeys: String, CodingKey { + case items = "ResponseItems" + } +} + +_ = ResponseModel(items: [Item()]).items +``` + +```swift +class ResponseModel { + @objc func foo() { + } +} +_ = ResponseModel() +``` + +```swift +public func foo() {} +``` + +```swift +protocol Foo {} + +extension Foo { + func bar() {} +} + +struct MyStruct: Foo {} +MyStruct().bar() +``` + +```swift +import XCTest +class MyTests: XCTestCase { + func testExample() {} +} +``` + +```swift +import XCTest +open class BestTestCase: XCTestCase {} +class MyTests: BestTestCase { + func testExample() {} +} +``` + +```swift + struct S { + var i: Int? = nil + func f() { + if let i { print(i) } + } + } + S().f() +``` + +```swift +enum Component { + case string(StaticString) + indirect case array([Component]) + indirect case optional(Component?) +} + +@resultBuilder +struct ComponentBuilder { + static func buildBlock(_ components: Component...) -> Component { + return .array(components) + } + + static func buildExpression(_ string: StaticString) -> Component { + return .string(string) + } + + static func buildOptional(_ component: Component?) -> Component { + return .optional(component) + } + + static func buildEither(first component: Component) -> Component { + return component + } + + static func buildEither(second component: Component) -> Component { + return component + } + + static func buildArray(_ components: [Component]) -> Component { + return .array(components) + } + + static func buildLimitedAvailability(_ component: Component) -> Component { + return component + } + + static func buildFinalResult(_ component: Component) -> Component { + return component + } + + static func buildPartialBlock(first component: Component) -> Component { + return component + } + + static func buildPartialBlock(accumulated component: Component, next: Component) -> Component { + return component + } +} + +func acceptComponentBuilder(@ComponentBuilder _ body: () -> Component) { + print(body()) +} + +acceptComponentBuilder { + "hello" +} +``` + +## Triggering Examples + +```swift +let ↓kConstant = 0 +``` + +```swift +struct Item {} +struct ↓ResponseModel: Codable { + let ↓items: [Item] + + enum ↓CodingKeys: String { + case items = "ResponseItems" + } +} +``` + +```swift +class ↓ResponseModel { + func ↓foo() { + } +} +``` + +```swift +// +// include_public_and_open: true +// + +public func ↓foo() {} + +``` + +```swift +protocol Foo { + func ↓bar1() +} + +extension Foo { + func bar1() {} + func ↓bar2() {} +} + +struct MyStruct: Foo {} +_ = MyStruct() +``` + +```swift +import XCTest +class ↓MyTests: NSObject { + func ↓testExample() {} +} +``` + +```swift +enum Component { + case string(StaticString) + indirect case array([Component]) + indirect case optional(Component?) +} + +struct ComponentBuilder { + func ↓buildExpression(_ string: StaticString) -> Component { + return .string(string) + } + + func ↓buildBlock(_ components: Component...) -> Component { + return .array(components) + } + + func ↓buildIf(_ value: Component?) -> Component { + return .optional(value) + } + + static func ↓buildABear(_ components: Component...) -> Component { + return .array(components) + } +} + +_ = ComponentBuilder() +``` + +```swift +protocol ↓Foo {} +extension Foo {} +``` + +```swift +class ↓C {} +extension C {} +``` \ No newline at end of file diff --git a/docs/description/unused_enumerated.md b/docs/description/unused_enumerated.md new file mode 100644 index 0000000..41793df --- /dev/null +++ b/docs/description/unused_enumerated.md @@ -0,0 +1,145 @@ +# Unused Enumerated + +When the index or the item is not used, `.enumerated()` can be removed. + +* **Identifier:** `unused_enumerated` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +for (idx, foo) in bar.enumerated() { } +``` + +```swift +for (_, foo) in bar.enumerated().something() { } +``` + +```swift +for (_, foo) in bar.something() { } +``` + +```swift +for foo in bar.enumerated() { } +``` + +```swift +for foo in bar { } +``` + +```swift +for (idx, _) in bar.enumerated().something() { } +``` + +```swift +for (idx, _) in bar.something() { } +``` + +```swift +for idx in bar.indices { } +``` + +```swift +for (section, (event, _)) in data.enumerated() {} +``` + +```swift +list.enumerated().map { idx, elem in "\(idx): \(elem)" } +``` + +```swift +list.enumerated().map { $0 + $1 } +``` + +```swift +list.enumerated().something().map { _, elem in elem } +``` + +```swift +list.enumerated().map { ($0.offset, $0.element) } +``` + +```swift +list.enumerated().map { ($0.0, $0.1) } +``` + +```swift +list.enumerated().map { + $1.enumerated().forEach { print($0, $1) } + return $0 +} +``` + +## Triggering Examples + +```swift +for (↓_, foo) in bar.enumerated() { } +``` + +```swift +for (↓_, foo) in abc.bar.enumerated() { } +``` + +```swift +for (↓_, foo) in abc.something().enumerated() { } +``` + +```swift +for (idx, ↓_) in bar.enumerated() { } +``` + +```swift +list.enumerated().map { idx, ↓_ in idx } +``` + +```swift +list.enumerated().map { ↓_, elem in elem } +``` + +```swift +list.↓enumerated().forEach { print($0) } +``` + +```swift +list.↓enumerated().map { $1 } +``` + +```swift +list.enumerated().map { + $1.↓enumerated().forEach { print($1) } + return $0 +} +``` + +```swift +list.↓enumerated().map { + $1.enumerated().forEach { print($0, $1) } + return 1 +} +``` + +```swift +list.↓enumerated().forEach { + let (i, _) = $0 +} +``` \ No newline at end of file diff --git a/docs/description/unused_import.md b/docs/description/unused_import.md new file mode 100644 index 0000000..7723e06 --- /dev/null +++ b/docs/description/unused_import.md @@ -0,0 +1,138 @@ +# Unused Import + +All imported modules should be required to make the file compile + +* **Identifier:** `unused_import` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** Yes +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ require_explicit_imports + + false +
+ allowed_transitive_imports + + [] +
+ always_keep_imports + + [] +
+ +## Non Triggering Examples + +```swift +import Dispatch // This is used +dispatchMain() +``` + +```swift +@testable import Dispatch +dispatchMain() +``` + +```swift +import Foundation +@objc +class A {} +``` + +```swift +import UnknownModule +func foo(error: Swift.Error) {} +``` + +```swift +@_exported import UnknownModule +``` + +```swift +import Foundation +let 👨‍👩‍👧‍👦 = #selector(NSArray.contains(_:)) +👨‍👩‍👧‍👦 == 👨‍👩‍👧‍👦 +``` + +```swift +// +// allowed_transitive_imports: [Foundation: ["CoreFoundation"]] +// + +import Foundation +enum E { + static let min: CGFloat = 44 +} + +``` + +## Triggering Examples + +```swift +↓import Dispatch +struct A { + static func dispatchMain() {} +} +A.dispatchMain() +``` + +```swift +↓import Foundation // This is unused +struct A { + static func dispatchMain() {} +} +A.dispatchMain() +↓import Dispatch + +``` + +```swift +↓import Foundation +dispatchMain() +``` + +```swift +↓import Foundation +// @objc +class A {} +``` + +```swift +↓import Foundation +import UnknownModule +func foo(error: Swift.Error) {} +``` + +```swift +↓import Swift +↓import SwiftShims +func foo(error: Swift.Error) {} +``` \ No newline at end of file diff --git a/docs/description/unused_optional_binding.md b/docs/description/unused_optional_binding.md new file mode 100644 index 0000000..26b767c --- /dev/null +++ b/docs/description/unused_optional_binding.md @@ -0,0 +1,98 @@ +# Unused Optional Binding + +Prefer `!= nil` over `let _ =` + +* **Identifier:** `unused_optional_binding` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ ignore_optional_try + + false +
+ +## Non Triggering Examples + +```swift +if let bar = Foo.optionalValue {} +``` + +```swift +if let (_, second) = getOptionalTuple() {} +``` + +```swift +if let (_, asd, _) = getOptionalTuple(), let bar = Foo.optionalValue {} +``` + +```swift +if foo() { let _ = bar() } +``` + +```swift +if foo() { _ = bar() } +``` + +```swift +if case .some(_) = self {} +``` + +```swift +if let point = state.find({ _ in true }) {} +``` + +## Triggering Examples + +```swift +if let ↓_ = Foo.optionalValue {} +``` + +```swift +if let a = Foo.optionalValue, let ↓_ = Foo.optionalValue2 {} +``` + +```swift +guard let a = Foo.optionalValue, let ↓_ = Foo.optionalValue2 {} +``` + +```swift +if let (first, second) = getOptionalTuple(), let ↓_ = Foo.optionalValue {} +``` + +```swift +if let (first, _) = getOptionalTuple(), let ↓_ = Foo.optionalValue {} +``` + +```swift +if let (_, second) = getOptionalTuple(), let ↓_ = Foo.optionalValue {} +``` + +```swift +if let ↓(_, _, _) = getOptionalTuple(), let bar = Foo.optionalValue {} +``` + +```swift +func foo() { if let ↓_ = bar {} } +``` \ No newline at end of file diff --git a/docs/description/unused_parameter.md b/docs/description/unused_parameter.md new file mode 100644 index 0000000..5b080ef --- /dev/null +++ b/docs/description/unused_parameter.md @@ -0,0 +1,139 @@ +# Unused Parameter + +Other than unused local variable declarations, unused function/initializer/subscript parameters are not marked by the Swift compiler. Since unused parameters are code smells, they should either be removed or replaced/shadowed by a wildcard '_' to indicate that they are being deliberately disregarded. + +* **Identifier:** `unused_parameter` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func f(a: Int) { + _ = a +} +``` + +```swift +func f(case: Int) { + _ = `case` +} +``` + +```swift +func f(a _: Int) {} +``` + +```swift +func f(_: Int) {} +``` + +```swift +func f(a: Int, b c: String) { + func g() { + _ = a + _ = c + } +} +``` + +```swift +func f(a: Int, c: Int) -> Int { + struct S { + let b = 1 + func f(a: Int, b: Int = 2) -> Int { a + b } + } + return a + c +} +``` + +```swift +func f(a: Int?) { + if let a {} +} +``` + +```swift +func f(a: Int) { + let a = a + return a +} +``` + +```swift +func f(`operator`: Int) -> Int { `operator` } +``` + +## Triggering Examples + +```swift +func f(↓a: Int) {} +``` + +```swift +func f(↓a: Int, b ↓c: String) {} +``` + +```swift +func f(↓a: Int, b ↓c: String) { + func g(a: Int, ↓b: Double) { + _ = a + } +} +``` + +```swift +struct S { + let a: Int + + init(a: Int, ↓b: Int) { + func f(↓a: Int, b: Int) -> Int { b } + self.a = f(a: a, b: 0) + } +} +``` + +```swift +struct S { + subscript(a: Int, ↓b: Int) { + func f(↓a: Int, b: Int) -> Int { b } + return f(a: a, b: 0) + } +} +``` + +```swift +func f(↓a: Int, ↓b: Int, c: Int) -> Int { + struct S { + let b = 1 + func f(a: Int, ↓c: Int = 2) -> Int { a + b } + } + return S().f(a: c) +} +``` + +```swift +func f(↓a: Int, c: String) { + let a = 1 + return a + c +} +``` \ No newline at end of file diff --git a/docs/description/unused_setter_value.md b/docs/description/unused_setter_value.md new file mode 100644 index 0000000..3e44b93 --- /dev/null +++ b/docs/description/unused_setter_value.md @@ -0,0 +1,139 @@ +# Unused Setter Value + +Setter value is not used + +* **Identifier:** `unused_setter_value` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +var aValue: String { + get { + return Persister.shared.aValue + } + set { + Persister.shared.aValue = newValue + } +} +``` + +```swift +var aValue: String { + set { + Persister.shared.aValue = newValue + } + get { + return Persister.shared.aValue + } +} +``` + +```swift +var aValue: String { + get { + return Persister.shared.aValue + } + set(value) { + Persister.shared.aValue = value + } +} +``` + +```swift +override var aValue: String { + get { + return Persister.shared.aValue + } + set { } +} +``` + +## Triggering Examples + +```swift +var aValue: String { + get { + return Persister.shared.aValue + } + ↓set { + Persister.shared.aValue = aValue + } +} +``` + +```swift +var aValue: String { + ↓set { + Persister.shared.aValue = aValue + } + get { + return Persister.shared.aValue + } +} +``` + +```swift +var aValue: String { + get { + return Persister.shared.aValue + } + ↓set { + Persister.shared.aValue = aValue + } +} +``` + +```swift +var aValue: String { + get { + let newValue = Persister.shared.aValue + return newValue + } + ↓set { + Persister.shared.aValue = aValue + } +} +``` + +```swift +var aValue: String { + get { + return Persister.shared.aValue + } + ↓set(value) { + Persister.shared.aValue = aValue + } +} +``` + +```swift +override var aValue: String { + get { + return Persister.shared.aValue + } + ↓set { + Persister.shared.aValue = aValue + } +} +``` \ No newline at end of file diff --git a/docs/description/valid_ibinspectable.md b/docs/description/valid_ibinspectable.md new file mode 100644 index 0000000..27842cf --- /dev/null +++ b/docs/description/valid_ibinspectable.md @@ -0,0 +1,138 @@ +# Valid IBInspectable + +@IBInspectable should be applied to variables only, have its type explicit and be of a supported type + +* **Identifier:** `valid_ibinspectable` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Foo { + @IBInspectable private var x: Int +} +``` + +```swift +class Foo { + @IBInspectable private var x: String? +} +``` + +```swift +class Foo { + @IBInspectable private var x: String! +} +``` + +```swift +class Foo { + @IBInspectable private var count: Int = 0 +} +``` + +```swift +class Foo { + private var notInspectable = 0 +} +``` + +```swift +class Foo { + private let notInspectable: Int +} +``` + +```swift +class Foo { + private let notInspectable: UInt8 +} +``` + +```swift +extension Foo { + @IBInspectable var color: UIColor { + set { + self.bar.textColor = newValue + } + + get { + return self.bar.textColor + } + } +} +``` + +```swift +class Foo { + @IBInspectable var borderColor: UIColor? = nil { + didSet { + updateAppearance() + } + } +} +``` + +## Triggering Examples + +```swift +class Foo { + @IBInspectable private ↓let count: Int +} +``` + +```swift +class Foo { + @IBInspectable private ↓var insets: UIEdgeInsets +} +``` + +```swift +class Foo { + @IBInspectable private ↓var count = 0 +} +``` + +```swift +class Foo { + @IBInspectable private ↓var count: Int? +} +``` + +```swift +class Foo { + @IBInspectable private ↓var count: Int! +} +``` + +```swift +class Foo { + @IBInspectable private ↓var count: Optional +} +``` + +```swift +class Foo { + @IBInspectable private ↓var x: Optional +} +``` \ No newline at end of file diff --git a/docs/description/vertical_parameter_alignment.md b/docs/description/vertical_parameter_alignment.md new file mode 100644 index 0000000..bab4e06 --- /dev/null +++ b/docs/description/vertical_parameter_alignment.md @@ -0,0 +1,131 @@ +# Vertical Parameter Alignment + +Function parameters should be aligned vertically if they're in multiple lines in a declaration + +* **Identifier:** `vertical_parameter_alignment` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary) { } +``` + +```swift +func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary) -> [StyleViolation] +``` + +```swift +func foo(bar: Int) +``` + +```swift +func foo(bar: Int) -> String +``` + +```swift +func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary) + -> [StyleViolation] +``` + +```swift +func validateFunction( + _ file: SwiftLintFile, kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary) -> [StyleViolation] +``` + +```swift +func validateFunction( + _ file: SwiftLintFile, kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary +) -> [StyleViolation] +``` + +```swift +func regex(_ pattern: String, + options: NSRegularExpression.Options = [.anchorsMatchLines, + .dotMatchesLineSeparators]) -> NSRegularExpression +``` + +```swift +func foo(a: Void, + b: [String: String] = + [:]) { +} +``` + +```swift +func foo(data: (size: CGSize, + identifier: String)) {} +``` + +```swift +func foo(data: Data, + @ViewBuilder content: @escaping (Data.Element.IdentifiedValue) -> Content) {} +``` + +```swift +class A { + init(bar: Int) +} +``` + +```swift +class A { + init(foo: Int, + bar: String) +} +``` + +## Triggering Examples + +```swift +func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind, + ↓dictionary: SourceKittenDictionary) { } +``` + +```swift +func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind, + ↓dictionary: SourceKittenDictionary) { } +``` + +```swift +func validateFunction(_ file: SwiftLintFile, + ↓kind: SwiftDeclarationKind, + ↓dictionary: SourceKittenDictionary) { } +``` + +```swift +func foo(data: Data, + ↓@ViewBuilder content: @escaping (Data.Element.IdentifiedValue) -> Content) {} +``` + +```swift +class A { + init(data: Data, + ↓@ViewBuilder content: @escaping (Data.Element.IdentifiedValue) -> Content) {} +} +``` \ No newline at end of file diff --git a/docs/description/vertical_parameter_alignment_on_call.md b/docs/description/vertical_parameter_alignment_on_call.md new file mode 100644 index 0000000..068c45c --- /dev/null +++ b/docs/description/vertical_parameter_alignment_on_call.md @@ -0,0 +1,158 @@ +# Vertical Parameter Alignment on Call + +Function parameters should be aligned vertically if they're in multiple lines in a method call + +* **Identifier:** `vertical_parameter_alignment_on_call` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +foo(param1: 1, param2: bar + param3: false, param4: true) +``` + +```swift +foo(param1: 1, param2: bar) +``` + +```swift +foo(param1: 1, param2: bar + param3: false, + param4: true) +``` + +```swift +foo( + param1: 1 +) { _ in } +``` + +```swift +UIView.animate(withDuration: 0.4, animations: { + blurredImageView.alpha = 1 +}, completion: { _ in + self.hideLoading() +}) +``` + +```swift +UIView.animate(withDuration: 0.4, animations: { + blurredImageView.alpha = 1 +}, +completion: { _ in + self.hideLoading() +}) +``` + +```swift +UIView.animate(withDuration: 0.4, animations: { + blurredImageView.alpha = 1 +} { _ in + self.hideLoading() +} +``` + +```swift +foo(param1: 1, param2: { _ in }, + param3: false, param4: true) +``` + +```swift +foo({ _ in + bar() + }, + completion: { _ in + baz() + } +) +``` + +```swift +foo(param1: 1, param2: [ + 0, + 1 +], param3: 0) +``` + +```swift +myFunc(foo: 0, + bar: baz == 0) +``` + +```swift +UIViewPropertyAnimator.runningPropertyAnimator( + withDuration: 2.0, + delay: 0.0, + options: [.curveEaseIn] +) { + // animations +} completion: { _ in + // completion +} +``` + +## Triggering Examples + +```swift +foo(param1: 1, param2: bar, + ↓param3: false, param4: true) +``` + +```swift +foo(param1: 1, param2: bar, + ↓param3: false, param4: true) +``` + +```swift +foo(param1: 1, param2: bar, + ↓param3: false, + ↓param4: true) +``` + +```swift +foo(param1: 1, + ↓param2: { _ in }) +``` + +```swift +foo(param1: 1, + param2: { _ in +}, param3: 2, + ↓param4: 0) +``` + +```swift +foo(param1: 1, param2: { _ in }, + ↓param3: false, param4: true) +``` + +```swift +myFunc(foo: 0, + ↓bar: baz == 0) +``` + +```swift +myFunc(foo: 0, bar: + baz == 0, ↓baz: true) +``` \ No newline at end of file diff --git a/docs/description/vertical_whitespace.md b/docs/description/vertical_whitespace.md new file mode 100644 index 0000000..bf3cbaf --- /dev/null +++ b/docs/description/vertical_whitespace.md @@ -0,0 +1,85 @@ +# Vertical Whitespace + +Limit vertical whitespace to a single empty line. + +* **Identifier:** `vertical_whitespace` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ max_empty_lines + + 1 +
+ +## Non Triggering Examples + +```swift +let abc = 0 + +``` + +```swift +let abc = 0 + + +``` + +```swift +/* bcs + + + +*/ +``` + +```swift +// bca + + +``` + +## Triggering Examples + +```swift +let aaaa = 0 + + + +``` + +```swift +struct AAAA {} + + + + +``` + +```swift +class BBBB {} + + + +``` \ No newline at end of file diff --git a/docs/description/vertical_whitespace_between_cases.md b/docs/description/vertical_whitespace_between_cases.md new file mode 100644 index 0000000..402a16e --- /dev/null +++ b/docs/description/vertical_whitespace_between_cases.md @@ -0,0 +1,164 @@ +# Vertical Whitespace Between Cases + +Include a single empty line between switch cases + +* **Identifier:** `vertical_whitespace_between_cases` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +switch x { + +case 0..<5: + print("x is low") + +case 5..<10: + print("x is high") + +default: + print("x is invalid") + +@unknown default: + print("x is out of this world") +} +``` + +```swift +switch x { +case .valid: + print("multiple ...") + print("... lines") + +case .invalid: + print("multiple ...") + print("... lines") +} +``` + +```swift +switch x { +case .valid: + print("x is valid") + +case .invalid: + print("x is invalid") +} +``` + +```swift +switch x { +case 0..<5: + print("x is low") + +case 5..<10: + print("x is high") + +default: + print("x is invalid") +} +``` + +```swift +switch x { +case 0..<5: + print("x is valid") + +default: + print("x is invalid") +} +``` + +```swift +switch x { +case 0..<5: + return "x is valid" + +default: + return "x is invalid" + +@unknown default: + print("x is out of this world") +} +``` + +```swift +switch x { +case 0..<5: print("x is low") +case 5..<10: print("x is high") +default: print("x is invalid") +@unknown default: print("x is out of this world") +} +``` + +```swift +switch x { +case 1: + print("one") + +default: + print("not one") +} +``` + +## Triggering Examples + +```swift +switch x { +case .valid: + print("multiple ...") + print("... lines") +↓case .invalid: + print("multiple ...") + print("... lines") +} +``` + +```swift +switch x { +case .valid: + print("x is valid") +↓case .invalid: + print("x is invalid") +} +``` + +```swift +switch x { +case 0..<5: + print("x is valid") +↓default: + print("x is invalid") +} +``` + +```swift +switch x { +case 0..<5: + return "x is valid" +↓default: + return "x is invalid" +↓@unknown default: + print("x is out of this world") +} +``` \ No newline at end of file diff --git a/docs/description/vertical_whitespace_closing_braces.md b/docs/description/vertical_whitespace_closing_braces.md new file mode 100644 index 0000000..84e707d --- /dev/null +++ b/docs/description/vertical_whitespace_closing_braces.md @@ -0,0 +1,206 @@ +# Vertical Whitespace before Closing Braces + +Don't include vertical whitespace (empty line) before closing braces + +* **Identifier:** `vertical_whitespace_closing_braces` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ only_enforce_before_trivial_lines + + false +
+ +## Non Triggering Examples + +```swift +[ +1, +2, +3 +] +``` + +```swift +do { + print("x is 5") +} +``` + +```swift +do { + print("x is 5") +} +``` + +```swift +do { + print("x is 5") +} +``` + +```swift +foo( + x: 5, + y:6 +) +``` + +```swift +func foo() { + run(5) { x in + print(x) + } +} +``` + +```swift +// +// only_enforce_before_trivial_lines: true +// + +print([ + 1 +]) + +``` + +```swift +// +// only_enforce_before_trivial_lines: true +// + +print([foo { + var sum = 0 + for i in 1...5 { sum += i } + return sum + +}, foo { + var mul = 1 + for i in 1...5 { mul *= i } + return mul +}]) + +``` + +```swift +[1, 2].map { $0 }.filter { true } +``` + +```swift +[1, 2].map { $0 }.filter { num in true } +``` + +```swift +/* + class X { + + let x = 5 + + } +*/ +``` + +## Triggering Examples + +```swift +[ +1, +2, +3 +↓ +] +``` + +```swift +do { + print("x is 5") +↓ + +} +``` + +```swift +do { + print("x is 5") +↓ + +} +``` + +```swift +do { + print("x is 5") +↓ +} +``` + +```swift +foo( + x: 5, + y:6 +↓ +) +``` + +```swift +func foo() { + run(5) { x in + print(x) + } +↓ +} +``` + +```swift +// +// only_enforce_before_trivial_lines: true +// + +print([ + 1 +↓ +]) + +``` + +```swift +// +// only_enforce_before_trivial_lines: true +// + +print([foo { + var sum = 0 + for i in 1...5 { sum += i } + return sum + +}, foo { + var mul = 1 + for i in 1...5 { mul *= i } + return mul +↓ +}]) + +``` \ No newline at end of file diff --git a/docs/description/vertical_whitespace_opening_braces.md b/docs/description/vertical_whitespace_opening_braces.md new file mode 100644 index 0000000..f754086 --- /dev/null +++ b/docs/description/vertical_whitespace_opening_braces.md @@ -0,0 +1,188 @@ +# Vertical Whitespace after Opening Braces + +Don't include vertical whitespace (empty line) after opening braces + +* **Identifier:** `vertical_whitespace_opening_braces` +* **Enabled by default:** No +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +/* + class X { + + let x = 5 + + } +*/ +``` + +```swift +// [1, 2].map { $0 }.filter { num in true } +``` + +```swift +KingfisherManager.shared.retrieveImage(with: url, options: nil, progressBlock: nil) { image, _, _, _ in + guard let img = image else { return } +} +``` + +```swift +[ +1, +2, +3 +] +``` + +```swift +[1, 2].map { $0 }.filter { num in true } +``` + +```swift +[1, 2].map { $0 }.foo() +``` + +```swift +class X { + struct Y { + class Z { + } + } +} +``` + +```swift +foo( + x: 5, + y:6 +) +``` + +```swift +foo({ }) { _ in + self.dismiss(animated: false, completion: { + }) +} +``` + +```swift +func foo() { + run(5) { x in + print(x) + } +} +``` + +```swift +if x == 5 { + print("x is 5") +} +``` + +```swift +if x == 5 { + print("x is 5") +} +``` + +```swift +struct MyStruct { + let x = 5 +} +``` + +## Triggering Examples + +```swift +KingfisherManager.shared.retrieveImage(with: url, options: nil, progressBlock: nil) { image, _, _, _ in +↓ + guard let img = image else { return } +} +``` + +```swift +[ +↓ +1, +2, +3 +] +``` + +```swift +class X { + struct Y { +↓ + class Z { + } + } +} +``` + +```swift +foo( +↓ + x: 5, + y:6 +) +``` + +```swift +foo({ }) { _ in +↓ + self.dismiss(animated: false, completion: { + }) +} +``` + +```swift +func foo() { +↓ + run(5) { x in + print(x) + } +} +``` + +```swift +if x == 5 { +↓ + + print("x is 5") +} +``` + +```swift +if x == 5 { +↓ + print("x is 5") +} +``` + +```swift +struct MyStruct { +↓ + let x = 5 +} +``` \ No newline at end of file diff --git a/docs/description/void_function_in_ternary.md b/docs/description/void_function_in_ternary.md new file mode 100644 index 0000000..d0c03b3 --- /dev/null +++ b/docs/description/void_function_in_ternary.md @@ -0,0 +1,145 @@ +# Void Function in Ternary + +Using ternary to call Void functions should be avoided + +* **Identifier:** `void_function_in_ternary` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.1.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let result = success ? foo() : bar() +``` + +```swift +if success { + askQuestion() +} else { + exit() +} +``` + +```swift +var price: Double { + return hasDiscount ? calculatePriceWithDiscount() : calculateRegularPrice() +} +``` + +```swift +foo(x == 2 ? a() : b()) +``` + +```swift +chevronView.image = collapsed ? .icon(.mediumChevronDown) : .icon(.mediumChevronUp) +``` + +```swift +array.map { elem in + elem.isEmpty() ? .emptyValue() : .number(elem) +} +``` + +```swift +func compute(data: [Int]) -> Int { + data.isEmpty ? 0 : expensiveComputation(data) +} +``` + +```swift +var value: Int { + mode == .fast ? fastComputation() : expensiveComputation() +} +``` + +```swift +var value: Int { + get { + mode == .fast ? fastComputation() : expensiveComputation() + } +} +``` + +```swift +subscript(index: Int) -> Int { + get { + index == 0 ? defaultValue() : compute(index) + } +``` + +```swift +subscript(index: Int) -> Int { + index == 0 ? defaultValue() : compute(index) +``` + +## Triggering Examples + +```swift +success ↓? askQuestion() : exit() +``` + +```swift +perform { elem in + elem.isEmpty() ↓? .emptyValue() : .number(elem) + return 1 +} +``` + +```swift +DispatchQueue.main.async { + self.sectionViewModels[section].collapsed.toggle() + self.sectionViewModels[section].collapsed + ↓? self.tableView.deleteRows(at: [IndexPath(row: 0, section: section)], with: .automatic) + : self.tableView.insertRows(at: [IndexPath(row: 0, section: section)], with: .automatic) + self.tableView.scrollToRow(at: IndexPath(row: NSNotFound, section: section), at: .top, animated: true) +} +``` + +```swift +subscript(index: Int) -> Int { + index == 0 ↓? something() : somethingElse(index) + return index +``` + +```swift +var value: Int { + mode == .fast ↓? something() : somethingElse() + return 0 +} +``` + +```swift +var value: Int { + get { + mode == .fast ↓? something() : somethingElse() + return 0 + } +} +``` + +```swift +subscript(index: Int) -> Int { + get { + index == 0 ↓? something() : somethingElse(index) + return index + } +``` \ No newline at end of file diff --git a/docs/description/void_return.md b/docs/description/void_return.md new file mode 100644 index 0000000..985e368 --- /dev/null +++ b/docs/description/void_return.md @@ -0,0 +1,118 @@ +# Void Return + +Prefer `-> Void` over `-> ()` + +* **Identifier:** `void_return` +* **Enabled by default:** Yes +* **Supports autocorrection:** Yes +* **Kind:** style +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +let abc: () -> Void = {} +``` + +```swift +let abc: () -> (VoidVoid) = {} +``` + +```swift +func foo(completion: () -> Void) +``` + +```swift +let foo: (ConfigurationTests) -> () throws -> Void +``` + +```swift +let foo: (ConfigurationTests) -> () throws -> Void +``` + +```swift +let foo: (ConfigurationTests) ->() throws -> Void +``` + +```swift +let foo: (ConfigurationTests) -> () -> Void +``` + +```swift +let foo: () -> () async -> Void +``` + +```swift +let foo: () -> () async throws -> Void +``` + +```swift +let foo: () -> () async -> Void +``` + +```swift +func foo() -> () async throws -> Void {} +``` + +```swift +func foo() async throws -> () async -> Void { return {} } +``` + +```swift +func foo() -> () async -> Int { 1 } +``` + +## Triggering Examples + +```swift +let abc: () -> ↓() = {} +``` + +```swift +let abc: () -> ↓(Void) = {} +``` + +```swift +let abc: () -> ↓( Void ) = {} +``` + +```swift +func foo(completion: () -> ↓()) +``` + +```swift +func foo(completion: () -> ↓( )) +``` + +```swift +func foo(completion: () -> ↓(Void)) +``` + +```swift +let foo: (ConfigurationTests) -> () throws -> ↓() +``` + +```swift +func foo() async -> ↓() +``` + +```swift +func foo() async throws -> ↓() +``` \ No newline at end of file diff --git a/docs/description/weak_delegate.md b/docs/description/weak_delegate.md new file mode 100644 index 0000000..a2b4313 --- /dev/null +++ b/docs/description/weak_delegate.md @@ -0,0 +1,145 @@ +# Weak Delegate + +Delegates should be weak to avoid reference cycles + +* **Identifier:** `weak_delegate` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +class Foo { + weak var delegate: SomeProtocol? +} +``` + +```swift +class Foo { + weak var someDelegate: SomeDelegateProtocol? +} +``` + +```swift +class Foo { + weak var delegateScroll: ScrollDelegate? +} +``` + +```swift +class Foo { + var scrollHandler: ScrollDelegate? +} +``` + +```swift +func foo() { + var delegate: SomeDelegate +} +``` + +```swift +class Foo { + var delegateNotified: Bool? +} +``` + +```swift +protocol P { + var delegate: AnyObject? { get set } +} +``` + +```swift +class Foo { + protocol P { + var delegate: AnyObject? { get set } +} +} +``` + +```swift +class Foo { + var computedDelegate: ComputedDelegate { + return bar() +} +} +``` + +```swift +class Foo { + var computedDelegate: ComputedDelegate { + get { + return bar() + } + } +``` + +```swift +struct Foo { + @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate +} +``` + +```swift +struct Foo { + @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate +} +``` + +```swift +struct Foo { + @WKExtensionDelegateAdaptor(ExtensionDelegate.self) var extensionDelegate +} +``` + +```swift +class Foo { + func makeDelegate() -> SomeDelegate { + let delegate = SomeDelegate() + return delegate + } +} +``` + +## Triggering Examples + +```swift +class Foo { + ↓var delegate: SomeProtocol? +} +``` + +```swift +class Foo { + ↓var scrollDelegate: ScrollDelegate? +} +``` + +```swift +class Foo { + ↓var delegate: SomeProtocol? { + didSet { + print("Updated delegate") + } + } +``` \ No newline at end of file diff --git a/docs/description/xct_specific_matcher.md b/docs/description/xct_specific_matcher.md new file mode 100644 index 0000000..465f2f9 --- /dev/null +++ b/docs/description/xct_specific_matcher.md @@ -0,0 +1,398 @@ +# XCTest Specific Matcher + +Prefer specific XCTest matchers over `XCTAssertEqual` and `XCTAssertNotEqual`. + +* **Identifier:** `xct_specific_matcher` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ matchers + + [one-argument-asserts, two-argument-asserts] +
+ +## Non Triggering Examples + +```swift +XCTAssert(foo +``` + +```swift +XCTAssertFalse(foo) +``` + +```swift +XCTAssertTrue(foo) +``` + +```swift +XCTAssertNil(foo) +``` + +```swift +XCTAssertNotNil(foo) +``` + +```swift +XCTAssertEqual(foo, 2) +``` + +```swift +XCTAssertNotEqual(foo, "false") +``` + +```swift +XCTAssertEqual(foo, [1, 2, 3, true]) +``` + +```swift +XCTAssertEqual(foo, [1, 2, 3, false]) +``` + +```swift +XCTAssertEqual(foo, [1, 2, 3, nil]) +``` + +```swift +XCTAssertEqual(foo, [true, nil, true, nil]) +``` + +```swift +XCTAssertEqual([1, 2, 3, true], foo) +``` + +```swift +XCTAssertEqual([1, 2, 3, false], foo) +``` + +```swift +XCTAssertEqual([1, 2, 3, nil], foo) +``` + +```swift +XCTAssertEqual([true, nil, true, nil], foo) +``` + +```swift +XCTAssertEqual(2, foo) +``` + +```swift +XCTAssertNotEqual("false"), foo) +``` + +```swift +XCTAssertEqual(false, foo?.bar) +``` + +```swift +XCTAssertEqual(true, foo?.bar) +``` + +```swift +XCTAssert( foo ) +``` + +```swift +XCTAssertFalse( foo ) +``` + +```swift +XCTAssertTrue( foo ) +``` + +```swift +XCTAssertNil( foo ) +``` + +```swift +XCTAssertNotNil( foo ) +``` + +```swift +XCTAssertEqual( foo , 2 ) +``` + +```swift +XCTAssertNotEqual( foo, "false") +``` + +```swift +XCTAssertEqual(foo?.bar, false) +``` + +```swift +XCTAssertEqual(foo?.bar, true) +``` + +```swift +XCTAssertNil(foo?.bar) +``` + +```swift +XCTAssertNotNil(foo?.bar) +``` + +```swift +XCTAssertEqual(foo?.bar, 2) +``` + +```swift +XCTAssertNotEqual(foo?.bar, "false") +``` + +```swift +XCTAssertEqual(foo?.bar, toto()) +``` + +```swift +XCTAssertEqual(foo?.bar, .toto(.zoo)) +``` + +```swift +XCTAssertEqual(toto(), foo?.bar) +``` + +```swift +XCTAssertEqual(.toto(.zoo), foo?.bar) +``` + +```swift +XCTAssert(foo.self == bar) +``` + +```swift +XCTAssertTrue(type(of: foo) != Int.self) +``` + +```swift +XCTAssertTrue(a == (1, 3, 5) +``` + +## Triggering Examples + +```swift +↓XCTAssertEqual(foo, true) +``` + +```swift +↓XCTAssertEqual(foo, false) +``` + +```swift +↓XCTAssertEqual(foo, nil) +``` + +```swift +↓XCTAssertNotEqual(foo, true) +``` + +```swift +↓XCTAssertNotEqual(foo, false) +``` + +```swift +↓XCTAssertNotEqual(foo, nil) +``` + +```swift +↓XCTAssertEqual(true, foo) +``` + +```swift +↓XCTAssertEqual(false, foo) +``` + +```swift +↓XCTAssertEqual(nil, foo) +``` + +```swift +↓XCTAssertNotEqual(true, foo) +``` + +```swift +↓XCTAssertNotEqual(false, foo) +``` + +```swift +↓XCTAssertNotEqual(nil, foo) +``` + +```swift +↓XCTAssertEqual(foo, true, "toto") +``` + +```swift +↓XCTAssertEqual(foo, false, "toto") +``` + +```swift +↓XCTAssertEqual(foo, nil, "toto") +``` + +```swift +↓XCTAssertNotEqual(foo, true, "toto") +``` + +```swift +↓XCTAssertNotEqual(foo, false, "toto") +``` + +```swift +↓XCTAssertNotEqual(foo, nil, "toto") +``` + +```swift +↓XCTAssertEqual(true, foo, "toto") +``` + +```swift +↓XCTAssertEqual(false, foo, "toto") +``` + +```swift +↓XCTAssertEqual(nil, foo, "toto") +``` + +```swift +↓XCTAssertNotEqual(true, foo, "toto") +``` + +```swift +↓XCTAssertNotEqual(false, foo, "toto") +``` + +```swift +↓XCTAssertNotEqual(nil, foo, "toto") +``` + +```swift +↓XCTAssertEqual(foo,true) +``` + +```swift +↓XCTAssertEqual( foo , false ) +``` + +```swift +↓XCTAssertEqual( foo , nil ) +``` + +```swift +↓XCTAssertEqual(true, [1, 2, 3, true].hasNumbers()) +``` + +```swift +↓XCTAssertEqual([1, 2, 3, true].hasNumbers(), true) +``` + +```swift +↓XCTAssertEqual(foo?.bar, nil) +``` + +```swift +↓XCTAssertNotEqual(foo?.bar, nil) +``` + +```swift +↓XCTAssertEqual(nil, true) +``` + +```swift +↓XCTAssertEqual(nil, false) +``` + +```swift +↓XCTAssertEqual(true, nil) +``` + +```swift +↓XCTAssertEqual(false, nil) +``` + +```swift +↓XCTAssertEqual(nil, nil) +``` + +```swift +↓XCTAssertEqual(true, true) +``` + +```swift +↓XCTAssertEqual(false, false) +``` + +```swift +↓XCTAssert(foo == bar) +``` + +```swift +↓XCTAssertTrue( foo == bar ) +``` + +```swift +↓XCTAssertFalse(1 == foo) +``` + +```swift +↓XCTAssert(foo == bar, "toto") +``` + +```swift +↓XCTAssert(foo != bar) +``` + +```swift +↓XCTAssertTrue( foo != bar ) +``` + +```swift +↓XCTAssertFalse(1 != foo) +``` + +```swift +↓XCTAssert(foo != bar, "toto") +``` + +```swift +↓XCTAssert( foo == nil) +``` + +```swift +↓XCTAssert(nil == foo +``` + +```swift +↓XCTAssertTrue( foo != nil) +``` + +```swift +↓XCTAssertFalse(nil != foo +``` + +```swift +↓XCTAssert(foo == nil, "toto") +``` \ No newline at end of file diff --git a/docs/description/xctfail_message.md b/docs/description/xctfail_message.md new file mode 100644 index 0000000..7e673a0 --- /dev/null +++ b/docs/description/xctfail_message.md @@ -0,0 +1,54 @@ +# XCTFail Message + +An XCTFail call should include a description of the assertion + +* **Identifier:** `xctfail_message` +* **Enabled by default:** Yes +* **Supports autocorrection:** No +* **Kind:** idiomatic +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +func testFoo() { + XCTFail("bar") +} +``` + +```swift +func testFoo() { + XCTFail(bar) +} +``` + +## Triggering Examples + +```swift +func testFoo() { + ↓XCTFail() +} +``` + +```swift +func testFoo() { + ↓XCTFail("") +} +``` \ No newline at end of file diff --git a/docs/description/yoda_condition.md b/docs/description/yoda_condition.md new file mode 100644 index 0000000..eaf9059 --- /dev/null +++ b/docs/description/yoda_condition.md @@ -0,0 +1,106 @@ +# Yoda Condition + +The constant literal should be placed on the right-hand side of the comparison operator + +* **Identifier:** `yoda_condition` +* **Enabled by default:** No +* **Supports autocorrection:** No +* **Kind:** lint +* **Analyzer rule:** No +* **Minimum Swift compiler version:** 5.0.0 +* **Default configuration:** + + + + + + + + + + +
KeyValue
+ severity + + warning +
+ +## Non Triggering Examples + +```swift +if foo == 42 {} +``` + +```swift +if foo <= 42.42 {} +``` + +```swift +guard foo >= 42 else { return } +``` + +```swift +guard foo != "str str" else { return } +``` + +```swift +while foo < 10 { } +``` + +```swift +while foo > 1 { } +``` + +```swift +while foo + 1 == 2 {} +``` + +```swift +if optionalValue?.property ?? 0 == 2 {} +``` + +```swift +if foo == nil {} +``` + +```swift +if flags & 1 == 1 {} +``` + +## Triggering Examples + +```swift +if ↓42 == foo {} +``` + +```swift +if ↓42.42 >= foo {} +``` + +```swift +guard ↓42 <= foo else { return } +``` + +```swift +guard ↓"str str" != foo else { return } +``` + +```swift +while ↓10 > foo { } +``` + +```swift +while ↓1 < foo { } +``` + +```swift +if ↓nil == foo {} +``` + +```swift +while ↓1 > i + 5 {} +``` + +```swift +if ↓200 <= i && i <= 299 || ↓600 <= i {} +``` \ No newline at end of file diff --git a/docs/multiple-tests/filter-files/patterns.xml b/docs/multiple-tests/filter-files/patterns.xml new file mode 100644 index 0000000..cb37919 --- /dev/null +++ b/docs/multiple-tests/filter-files/patterns.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/multiple-tests/filter-files/results.xml b/docs/multiple-tests/filter-files/results.xml new file mode 100644 index 0000000..27212ed --- /dev/null +++ b/docs/multiple-tests/filter-files/results.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/multiple-tests/filter-files/src/.swiftlint.yml b/docs/multiple-tests/filter-files/src/.swiftlint.yml new file mode 100644 index 0000000..7be436b --- /dev/null +++ b/docs/multiple-tests/filter-files/src/.swiftlint.yml @@ -0,0 +1,5 @@ +only_rules: + - closing_brace + - dynamic_inline + - first_where + - unused_enumerated diff --git a/docs/multiple-tests/filter-files/src/closing_brace.swift b/docs/multiple-tests/filter-files/src/closing_brace.swift new file mode 100644 index 0000000..842492f --- /dev/null +++ b/docs/multiple-tests/filter-files/src/closing_brace.swift @@ -0,0 +1,3 @@ +[].map({ } ) + +[].map({ } ) diff --git a/docs/multiple-tests/filter-files/src/dynamic_inline.swift b/docs/multiple-tests/filter-files/src/dynamic_inline.swift new file mode 100644 index 0000000..635fee5 --- /dev/null +++ b/docs/multiple-tests/filter-files/src/dynamic_inline.swift @@ -0,0 +1,22 @@ +class C { +@inline(__always) dynamic func f() {} +} + +class C { +@inline(__always) public dynamic func f() {} +} + +class C { +@inline(__always) dynamic internal func f() {} +} + +class C { +@inline(__always) +dynamic func f() {} +} + +class C { +@inline(__always) +dynamic +func f() {} +} diff --git a/docs/multiple-tests/multiple-config-submodules-and-custom-rules/patterns.xml b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/patterns.xml new file mode 100644 index 0000000..a36de62 --- /dev/null +++ b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/patterns.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/multiple-tests/multiple-config-submodules-and-custom-rules/results.xml b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/results.xml new file mode 100644 index 0000000..b9d9a7a --- /dev/null +++ b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/results.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/.swiftlint.yml b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/.swiftlint.yml new file mode 100644 index 0000000..8477628 --- /dev/null +++ b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/.swiftlint.yml @@ -0,0 +1,2 @@ +disabled_rules: + - todo diff --git a/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/main.swift b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/main.swift new file mode 100644 index 0000000..23dac9b --- /dev/null +++ b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/main.swift @@ -0,0 +1,5 @@ +// TODO: something special + +debugPrint("something to debug") + +// TODO [MAGIC-101]: yeah magic diff --git a/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/sub_module/.swiftlint.yml b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/sub_module/.swiftlint.yml new file mode 100644 index 0000000..74f4759 --- /dev/null +++ b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/sub_module/.swiftlint.yml @@ -0,0 +1,5 @@ +custom_rules: + jira_todo: + name: "TODOs and FIXMEs should be resolved or task should be created" + regex: '\b(?:TODO|FIXME)[^\[]*(?!\[[\w-]+\])[^\[]*$' + message: "TODO/FIXME is not acceptable without JIRA TASK ID. Include Jira ID in the message: `TODO: [ABC-XXX] Fix this line`" \ No newline at end of file diff --git a/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/sub_module/sub_main.swift b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/sub_module/sub_main.swift new file mode 100644 index 0000000..1c39712 --- /dev/null +++ b/docs/multiple-tests/multiple-config-submodules-and-custom-rules/src/sub_module/sub_main.swift @@ -0,0 +1,5 @@ +// TODO: submodule something special + +debugPrint("something to debug") + +// TODO [MAGIC-101]: submodule yeah magic diff --git a/docs/multiple-tests/multiple-files/patterns.xml b/docs/multiple-tests/multiple-files/patterns.xml new file mode 100644 index 0000000..a36de62 --- /dev/null +++ b/docs/multiple-tests/multiple-files/patterns.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/multiple-tests/multiple-files/results.xml b/docs/multiple-tests/multiple-files/results.xml new file mode 100644 index 0000000..b25e73f --- /dev/null +++ b/docs/multiple-tests/multiple-files/results.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/multiple-tests/multiple-files/src/.swiftlint.yml b/docs/multiple-tests/multiple-files/src/.swiftlint.yml new file mode 100644 index 0000000..7be436b --- /dev/null +++ b/docs/multiple-tests/multiple-files/src/.swiftlint.yml @@ -0,0 +1,5 @@ +only_rules: + - closing_brace + - dynamic_inline + - first_where + - unused_enumerated diff --git a/docs/multiple-tests/multiple-files/src/closing_brace.swift b/docs/multiple-tests/multiple-files/src/closing_brace.swift new file mode 100644 index 0000000..842492f --- /dev/null +++ b/docs/multiple-tests/multiple-files/src/closing_brace.swift @@ -0,0 +1,3 @@ +[].map({ } ) + +[].map({ } ) diff --git a/docs/multiple-tests/multiple-files/src/dynamic_inline.swift b/docs/multiple-tests/multiple-files/src/dynamic_inline.swift new file mode 100644 index 0000000..635fee5 --- /dev/null +++ b/docs/multiple-tests/multiple-files/src/dynamic_inline.swift @@ -0,0 +1,22 @@ +class C { +@inline(__always) dynamic func f() {} +} + +class C { +@inline(__always) public dynamic func f() {} +} + +class C { +@inline(__always) dynamic internal func f() {} +} + +class C { +@inline(__always) +dynamic func f() {} +} + +class C { +@inline(__always) +dynamic +func f() {} +} diff --git a/docs/multiple-tests/use-codacy-conf/patterns.xml b/docs/multiple-tests/use-codacy-conf/patterns.xml new file mode 100644 index 0000000..34aafb8 --- /dev/null +++ b/docs/multiple-tests/use-codacy-conf/patterns.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/multiple-tests/use-codacy-conf/results.xml b/docs/multiple-tests/use-codacy-conf/results.xml new file mode 100644 index 0000000..883bce8 --- /dev/null +++ b/docs/multiple-tests/use-codacy-conf/results.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/docs/multiple-tests/use-codacy-conf/src/.swiftlint.yml b/docs/multiple-tests/use-codacy-conf/src/.swiftlint.yml new file mode 100644 index 0000000..750359b --- /dev/null +++ b/docs/multiple-tests/use-codacy-conf/src/.swiftlint.yml @@ -0,0 +1,2 @@ +whitelist_rules: + - closing_brace diff --git a/docs/multiple-tests/use-codacy-conf/src/closing_brace.swift b/docs/multiple-tests/use-codacy-conf/src/closing_brace.swift new file mode 100644 index 0000000..842492f --- /dev/null +++ b/docs/multiple-tests/use-codacy-conf/src/closing_brace.swift @@ -0,0 +1,3 @@ +[].map({ } ) + +[].map({ } ) diff --git a/docs/multiple-tests/use-codacy-conf/src/dynamic_inline.swift b/docs/multiple-tests/use-codacy-conf/src/dynamic_inline.swift new file mode 100644 index 0000000..635fee5 --- /dev/null +++ b/docs/multiple-tests/use-codacy-conf/src/dynamic_inline.swift @@ -0,0 +1,22 @@ +class C { +@inline(__always) dynamic func f() {} +} + +class C { +@inline(__always) public dynamic func f() {} +} + +class C { +@inline(__always) dynamic internal func f() {} +} + +class C { +@inline(__always) +dynamic func f() {} +} + +class C { +@inline(__always) +dynamic +func f() {} +} diff --git a/docs/multiple-tests/with-config/patterns.xml b/docs/multiple-tests/with-config/patterns.xml new file mode 100644 index 0000000..a36de62 --- /dev/null +++ b/docs/multiple-tests/with-config/patterns.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/multiple-tests/with-config/results.xml b/docs/multiple-tests/with-config/results.xml new file mode 100644 index 0000000..27212ed --- /dev/null +++ b/docs/multiple-tests/with-config/results.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/multiple-tests/with-config/src/.swiftlint.yml b/docs/multiple-tests/with-config/src/.swiftlint.yml new file mode 100644 index 0000000..22259b0 --- /dev/null +++ b/docs/multiple-tests/with-config/src/.swiftlint.yml @@ -0,0 +1,2 @@ +only_rules: + - closing_brace diff --git a/docs/multiple-tests/with-config/src/closing_brace.swift b/docs/multiple-tests/with-config/src/closing_brace.swift new file mode 100644 index 0000000..842492f --- /dev/null +++ b/docs/multiple-tests/with-config/src/closing_brace.swift @@ -0,0 +1,3 @@ +[].map({ } ) + +[].map({ } ) diff --git a/docs/multiple-tests/with-config/src/dynamic_inline.swift b/docs/multiple-tests/with-config/src/dynamic_inline.swift new file mode 100644 index 0000000..635fee5 --- /dev/null +++ b/docs/multiple-tests/with-config/src/dynamic_inline.swift @@ -0,0 +1,22 @@ +class C { +@inline(__always) dynamic func f() {} +} + +class C { +@inline(__always) public dynamic func f() {} +} + +class C { +@inline(__always) dynamic internal func f() {} +} + +class C { +@inline(__always) +dynamic func f() {} +} + +class C { +@inline(__always) +dynamic +func f() {} +} diff --git a/docs/patterns.json b/docs/patterns.json new file mode 100644 index 0000000..40b7abe --- /dev/null +++ b/docs/patterns.json @@ -0,0 +1,1713 @@ +{ + "name" : "swiftlint", + "version" : "0.59.1", + "patterns" : [ { + "patternId" : "accessibility_label_for_image", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "accessibility_trait_for_button", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "anonymous_argument_in_multiline_closure", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "array_init", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "async_without_await", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "attribute_name_spacing", + "level" : "Error", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "attributes", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "balanced_xctest_lifecycle", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "blanket_disable_command", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "block_based_kvo", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "capture_variable", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "class_delegate_protocol", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "closing_brace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "closure_body_length", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "closure_end_indentation", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "closure_parameter_position", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "closure_spacing", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "collection_alignment", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "colon", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "comma", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "comma_inheritance", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "comment_spacing", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "compiler_protocol_init", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "computed_accessors_order", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "conditional_returns_on_newline", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "contains_over_filter_count", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "contains_over_filter_is_empty", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "contains_over_first_not_nil", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "contains_over_range_nil_comparison", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "contrasted_opening_brace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "control_statement", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "convenience_type", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "custom_rules", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "cyclomatic_complexity", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "deployment_target", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "direct_return", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "discarded_notification_center_observer", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "discouraged_assert", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "discouraged_direct_init", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "discouraged_none_name", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "discouraged_object_literal", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "discouraged_optional_boolean", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "discouraged_optional_collection", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "duplicate_conditions", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "duplicate_enum_cases", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "duplicate_imports", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "duplicated_key_in_dictionary_literal", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "dynamic_inline", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "empty_collection_literal", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "empty_count", + "level" : "Error", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "empty_enum_arguments", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "empty_parameters", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "empty_parentheses_with_trailing_closure", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "empty_string", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "empty_xctest_method", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "enum_case_associated_values_count", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "expiring_todo", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "explicit_acl", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "explicit_enum_raw_value", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "explicit_init", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "explicit_self", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "explicit_top_level_acl", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "explicit_type_interface", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "extension_access_modifier", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "fallthrough", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "fatal_error_message", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "file_header", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "file_length", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "file_name", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "file_name_no_space", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "file_types_order", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "final_test_case", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "first_where", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "flatmap_over_map_reduce", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "for_where", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "force_cast", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "force_try", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "force_unwrapping", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "function_body_length", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "function_default_parameter_at_end", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "function_parameter_count", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "generic_type_name", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "ibinspectable_in_extension", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "identical_operands", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "identifier_name", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "implicit_getter", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "implicit_return", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "implicitly_unwrapped_optional", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "inclusive_language", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "indentation_width", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "invalid_swiftlint_command", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "is_disjoint", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "joined_default_parameter", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "large_tuple", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "last_where", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "leading_whitespace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "legacy_cggeometry_functions", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "legacy_constant", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "legacy_constructor", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "legacy_hashing", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "legacy_multiple", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "legacy_nsgeometry_functions", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "legacy_objc_type", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "legacy_random", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "let_var_whitespace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "line_length", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "literal_expression_end_indentation", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "local_doc_comment", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "lower_acl_than_parent", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "mark", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "missing_docs", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "modifier_order", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "multiline_arguments", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "multiline_arguments_brackets", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "multiline_function_chains", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "multiline_literal_brackets", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "multiline_parameters", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "multiline_parameters_brackets", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "multiple_closures_with_trailing_closure", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "nesting", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "nimble_operator", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "no_empty_block", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "no_extension_access_modifier", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "no_fallthrough_only", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "no_grouping_extension", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "no_magic_numbers", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "no_space_in_method_call", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "non_optional_string_data_conversion", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "non_overridable_class_declaration", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "notification_center_detachment", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "ns_number_init_as_function_reference", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "nslocalizedstring_key", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "nslocalizedstring_require_bundle", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "nsobject_prefer_isequal", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "number_separator", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "object_literal", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "one_declaration_per_file", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "opening_brace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "operator_usage_whitespace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "operator_whitespace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "optional_data_string_conversion", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "optional_enum_case_matching", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "orphaned_doc_comment", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "overridden_super_call", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "override_in_extension", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "pattern_matching_keywords", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "period_spacing", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "prefer_key_path", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "prefer_nimble", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "prefer_self_in_static_references", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "prefer_self_type_over_type_of_self", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "prefer_type_checking", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "prefer_zero_over_explicit_init", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "prefixed_toplevel_constant", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "private_action", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "private_outlet", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "private_over_fileprivate", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "private_subject", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "private_swiftui_state", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "private_unit_test", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "prohibited_interface_builder", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "prohibited_super_call", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "protocol_property_accessors_order", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "quick_discouraged_call", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "quick_discouraged_focused_test", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "quick_discouraged_pending_test", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "raw_value_for_camel_cased_codable_enum", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "reduce_boolean", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "reduce_into", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "redundant_discardable_let", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "redundant_nil_coalescing", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "redundant_objc_attribute", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "redundant_optional_initialization", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "redundant_self_in_closure", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "redundant_sendable", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "redundant_set_access_control", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "redundant_string_enum_value", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "redundant_type_annotation", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "redundant_void_return", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "required_deinit", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "required_enum_case", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "return_arrow_whitespace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "return_value_from_void_function", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "self_binding", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "self_in_property_initialization", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "shorthand_argument", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "shorthand_operator", + "level" : "Error", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "shorthand_optional_binding", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "single_test_class", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "sorted_enum_cases", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "sorted_first_last", + "level" : "Warning", + "category" : "Performance", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "sorted_imports", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "statement_position", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "static_operator", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "static_over_final_class", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "strict_fileprivate", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "strong_iboutlet", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "superfluous_disable_command", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "superfluous_else", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "switch_case_alignment", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "switch_case_on_newline", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "syntactic_sugar", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "test_case_accessibility", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "todo", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "toggle_bool", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "trailing_closure", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "trailing_comma", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "trailing_newline", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "trailing_semicolon", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "trailing_whitespace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "type_body_length", + "level" : "Warning", + "category" : "Complexity", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "type_contents_order", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "type_name", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "typesafe_array_init", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unavailable_condition", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unavailable_function", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unhandled_throwing_task", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unneeded_break_in_switch", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unneeded_override", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unneeded_parentheses_in_closure_argument", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unneeded_synthesized_initializer", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unowned_variable_capture", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "untyped_error_in_catch", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unused_closure_parameter", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unused_control_flow_label", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unused_declaration", + "level" : "Error", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unused_enumerated", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unused_import", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unused_optional_binding", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "unused_parameter", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "unused_setter_value", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "valid_ibinspectable", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "vertical_parameter_alignment", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "vertical_parameter_alignment_on_call", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "vertical_whitespace", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "vertical_whitespace_between_cases", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "vertical_whitespace_closing_braces", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "vertical_whitespace_opening_braces", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "void_function_in_ternary", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "void_return", + "level" : "Warning", + "category" : "CodeStyle", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "weak_delegate", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "xct_specific_matcher", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "xctfail_message", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : true + }, { + "patternId" : "yoda_condition", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + } ] +} diff --git a/docs/tests/array_init.swift b/docs/tests/array_init.swift new file mode 100644 index 0000000..bdb33a9 --- /dev/null +++ b/docs/tests/array_init.swift @@ -0,0 +1,37 @@ +//#Patterns: array_init + +//#Issue: {"severity": "Warning", "line": 13, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "array_init"} +//#Issue: {"severity": "Warning", "line": 37, "patternId": "array_init"} + +foo.map({ $0 }) + +foo.map { $0 } + +foo.map { return $0 } + + foo.map { elem in + elem + } + + foo.map { elem in + return elem + } + + foo.map { (elem: String) in + elem + } + + foo.map { elem -> String in + elem + } + +foo.map { $0 /* a comment */ } + +foo.map { /* a comment */ $0 } diff --git a/docs/tests/block_based_kvo.swift b/docs/tests/block_based_kvo.swift new file mode 100644 index 0000000..3f0a797 --- /dev/null +++ b/docs/tests/block_based_kvo.swift @@ -0,0 +1,19 @@ +//#Patterns: block_based_kvo + +//#Issue: {"severity": "Warning", "line": 9, "patternId": "block_based_kvo"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "block_based_kvo"} + + + +class Foo: NSObject { + override func observeValue(forKeyPath keyPath: String?, of object: Any?, + change: [NSKeyValueChangeKey : Any]?, + context: UnsafeMutableRawPointer?) {} +} + + +class Foo: NSObject { + override func observeValue(forKeyPath keyPath: String?, of object: Any?, + change: Dictionary?, + context: UnsafeMutableRawPointer?) {} +} diff --git a/docs/tests/class_delegate_protocol.swift b/docs/tests/class_delegate_protocol.swift new file mode 100644 index 0000000..33ac6c4 --- /dev/null +++ b/docs/tests/class_delegate_protocol.swift @@ -0,0 +1,10 @@ +//#Patterns: class_delegate_protocol + +//#Issue: {"severity": "Warning", "line": 6, "patternId": "class_delegate_protocol"} +//#Issue: {"severity": "Warning", "line": 9, "patternId": "class_delegate_protocol"} + + protocol FooDelegate {} + + + protocol FooDelegate: Bar {} + diff --git a/docs/tests/closing_brace.swift b/docs/tests/closing_brace.swift new file mode 100644 index 0000000..7ccc470 --- /dev/null +++ b/docs/tests/closing_brace.swift @@ -0,0 +1,8 @@ +//#Patterns: closing_brace + +//#Issue: {"severity": "Warning", "line": 6, "patternId": "closing_brace"} +//#Issue: {"severity": "Warning", "line": 8, "patternId": "closing_brace"} + +[].map({ } ) + +[].map({ } ) diff --git a/src/main/resources/docs/tests/closure_end_indentation.swift b/docs/tests/closure_end_indentation.swift similarity index 56% rename from src/main/resources/docs/tests/closure_end_indentation.swift rename to docs/tests/closure_end_indentation.swift index 96401cf..27dea1b 100644 --- a/src/main/resources/docs/tests/closure_end_indentation.swift +++ b/docs/tests/closure_end_indentation.swift @@ -1,8 +1,8 @@ //#Patterns: closure_end_indentation -//#Issue: {"severity": "Info", "line": 10, "patternId": "closure_end_indentation"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "closure_end_indentation"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "closure_end_indentation"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "closure_end_indentation"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "closure_end_indentation"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "closure_end_indentation"} SignalProducer(values: [1, 2, 3]) .startWithNext { number in diff --git a/docs/tests/closure_spacing.swift b/docs/tests/closure_spacing.swift new file mode 100644 index 0000000..fe4510e --- /dev/null +++ b/docs/tests/closure_spacing.swift @@ -0,0 +1,14 @@ +//#Patterns: closure_spacing + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "closure_spacing"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "closure_spacing"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "closure_spacing"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "closure_spacing"} + + [].filter({$0.contains(location)}) + + [].map({$0}) + + ({each in return result.contains(where: ↓{e in return e}) }).count + + filter { sorted ↓{ $0 < $1}} diff --git a/docs/tests/colon.swift b/docs/tests/colon.swift new file mode 100644 index 0000000..de217cd --- /dev/null +++ b/docs/tests/colon.swift @@ -0,0 +1,177 @@ +//#Patterns: colon + +//#Issue: {"severity": "Warning", "line": 48, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 51, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 57, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 60, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 63, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 66, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 69, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 72, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 75, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 78, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 81, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 84, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 87, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 90, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 93, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 96, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 99, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 102, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 105, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 108, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 111, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 114, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 117, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 120, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 123, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 126, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 129, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 132, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 135, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 138, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 141, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 144, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 147, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 150, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 153, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 156, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 159, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 162, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 165, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 168, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 171, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 174, "patternId": "colon"} +//#Issue: {"severity": "Warning", "line": 177, "patternId": "colon"} + + let abc:Void + + + let abc: Void + + + let abc :Void + + + let abc : Void + + + let abc : [Void: Void] + + + let abc : (Void, String, Int) + + + let abc : ([Void], String, Int) + + + let abc : [([Void], String, Int)] + + + let abc: (Void, String, Int) + + + let abc: ([Void], String, Int) + + + let abc: [([Void], String, Int)] + + + let abc :String="def" + + + let abc :Int=0 + + + let abc :Int = 0 + + + let abc:Int=0 + + + let abc:Int = 0 + + + let abc:Enum=Enum.Value + + + func abc(def:Void) {} + + + func abc(def: Void) {} + + + func abc(def :Void) {} + + + func abc(def : Void) {} + + + func abc(def: Void, ghi :Void) {} + + + let abc = [Void:Void]() + + + let abc = [Void : Void]() + + + let abc = [Void: Void]() + + + let abc = [Void : Void]() + + + let abc = [1: [3 : 2], 3: 4] + + + let abc = [1: [3 : 2], 3↓: 4] + + + let abc: [String : Int] + + + let abc: [String:Int] + + + func foo(bar: [String : Int]) {} + + + func foo(bar: [String:Int]) {} + + + func foo() -> [String : Int] { return [:] } + + + func foo() -> [String:Int] { return [:] } + + + let abc : Any + + + let abc: [Any : Int] + + + let abc: [String : Any] + + + class Foo : Bar {} + + + class Foo:Bar {} + + + class Foo {} + + + class Foo {} + + + object.method(x: 5, y : "string") + + + object.method(x:5, y: "string") + + + object.method(x: 5, y: "string") diff --git a/docs/tests/comma.swift b/docs/tests/comma.swift new file mode 100644 index 0000000..018cc6f --- /dev/null +++ b/docs/tests/comma.swift @@ -0,0 +1,20 @@ +//#Patterns: comma + +//#Issue: {"severity": "Warning", "line": 9, "patternId": "comma"} +//#Issue: {"severity": "Warning", "line": 11, "patternId": "comma"} +//#Issue: {"severity": "Warning", "line": 13, "patternId": "comma"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "comma"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "comma"} + + func abc(a: String ,b: String) { } + + func abc(a: String ,b: String↓ ,c: String↓ ,d: String) { } + + abc(a: "string",b: "string" + + enum a { case a ,b } + + let result = plus( + first: 3 , // #683 + second: 4 + ) diff --git a/docs/tests/compiler_protocol_init.swift b/docs/tests/compiler_protocol_init.swift new file mode 100644 index 0000000..6ae9ab9 --- /dev/null +++ b/docs/tests/compiler_protocol_init.swift @@ -0,0 +1,14 @@ +//#Patterns: compiler_protocol_init + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "compiler_protocol_init"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "compiler_protocol_init"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "compiler_protocol_init"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "compiler_protocol_init"} + +let set = ↓Set(arrayLiteral: 1, 2) + +let set = ↓Set (arrayLiteral: 1, 2) + +let set = ↓Set.init(arrayLiteral: 1, 2) + +let set = ↓Set.init(arrayLiteral : 1, 2) diff --git a/docs/tests/conditional_returns_on_newline.swift b/docs/tests/conditional_returns_on_newline.swift new file mode 100644 index 0000000..ece920f --- /dev/null +++ b/docs/tests/conditional_returns_on_newline.swift @@ -0,0 +1,17 @@ +//#Patterns: conditional_returns_on_newline + +//#Issue: {"severity": "Warning", "line": 9, "patternId": "conditional_returns_on_newline"} +//#Issue: {"severity": "Warning", "line": 11, "patternId": "conditional_returns_on_newline"} +//#Issue: {"severity": "Warning", "line": 13, "patternId": "conditional_returns_on_newline"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "conditional_returns_on_newline"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "conditional_returns_on_newline"} + + guard true else { return } + + if true { return } + + if true { break } else { return } + + if true { break } else { return } + + if true { return "YES" } else { return "NO" } diff --git a/docs/tests/contains_over_first_not_nil.swift b/docs/tests/contains_over_first_not_nil.swift new file mode 100644 index 0000000..471d68d --- /dev/null +++ b/docs/tests/contains_over_first_not_nil.swift @@ -0,0 +1,32 @@ +//#Patterns: contains_over_first_not_nil + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "contains_over_first_not_nil"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "contains_over_first_not_nil"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "contains_over_first_not_nil"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "contains_over_first_not_nil"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "contains_over_first_not_nil"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "contains_over_first_not_nil"} + + + +myList.first { $0 % 2 == 0 } != nil + + + +myList.first(where: { $0 % 2 == 0 }) != nil + + + +myList.map { $0 + 1 }.first(where: { $0 % 2 == 0 }) != nil + + + +myList.first(where: someFunction) != nil + + + +myList.map { $0 + 1 }.first { $0 % 2 == 0 } != nil + + + +(myList.first { $0 % 2 == 0 }) != nil diff --git a/docs/tests/control_statement.swift b/docs/tests/control_statement.swift new file mode 100644 index 0000000..94b6833 --- /dev/null +++ b/docs/tests/control_statement.swift @@ -0,0 +1,41 @@ +//#Patterns: control_statement + +//#Issue: {"severity": "Warning", "line": 17, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 37, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 39, "patternId": "control_statement"} +//#Issue: {"severity": "Warning", "line": 41, "patternId": "control_statement"} + +if (condition) {} + +if(condition) {} + +if (condition == endIndex) {} + +if ((a || b) && (c || d)) {} + +if ((min...max).contains(value)) {} + +guard (condition) else {} + +while (condition) {} + +while(condition) {} + +do { ; } while(condition) {} + +do { ; } while (condition) {} + +switch (foo) {} + +do {} catch(let error as NSError) {} + +if (max(a, b) < c) {} diff --git a/src/main/resources/docs/tests/cyclomatic_complexity.swift b/docs/tests/cyclomatic_complexity.swift similarity index 81% rename from src/main/resources/docs/tests/cyclomatic_complexity.swift rename to docs/tests/cyclomatic_complexity.swift index 15c46e8..de6519e 100644 --- a/src/main/resources/docs/tests/cyclomatic_complexity.swift +++ b/docs/tests/cyclomatic_complexity.swift @@ -1,6 +1,6 @@ //#Patterns: cyclomatic_complexity -//#Issue: {"severity": "Info", "line": 5, "patternId": "cyclomatic_complexity"} +//#Issue: {"severity": "Warning", "line": 5, "patternId": "cyclomatic_complexity"} func f1() { if true { diff --git a/src/main/resources/docs/tests/discarded_notification_center_observer.swift b/docs/tests/discarded_notification_center_observer.swift similarity index 56% rename from src/main/resources/docs/tests/discarded_notification_center_observer.swift rename to docs/tests/discarded_notification_center_observer.swift index 7c390b1..7a963dc 100644 --- a/src/main/resources/docs/tests/discarded_notification_center_observer.swift +++ b/docs/tests/discarded_notification_center_observer.swift @@ -1,8 +1,8 @@ //#Patterns: discarded_notification_center_observer -//#Issue: {"severity": "Info", "line": 7, "patternId": "discarded_notification_center_observer"} -//#Issue: {"severity": "Info", "line": 10, "patternId": "discarded_notification_center_observer"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "discarded_notification_center_observer"} +//#Issue: {"severity": "Warning", "line": 7, "patternId": "discarded_notification_center_observer"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "discarded_notification_center_observer"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "discarded_notification_center_observer"} nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { } diff --git a/docs/tests/discouraged_direct_init.swift b/docs/tests/discouraged_direct_init.swift new file mode 100644 index 0000000..59c08b2 --- /dev/null +++ b/docs/tests/discouraged_direct_init.swift @@ -0,0 +1,42 @@ +//#Patterns: discouraged_direct_init + +//#Issue: {"severity": "Warning", "line": 15, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 36, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 39, "patternId": "discouraged_direct_init"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "discouraged_direct_init"} + + +UIDevice() + + +Bundle() + + +let foo = UIDevice() + + +let foo = Bundle() + + +let foo = bar(bundle: Bundle(), device: UIDevice()) + + +UIDevice.init() + + +Bundle.init() + + +let foo = UIDevice.init() + + +let foo = Bundle.init() + + +let foo = bar(bundle: Bundle.init(), device: UIDevice.init()) diff --git a/docs/tests/discouraged_object_literal.swift b/docs/tests/discouraged_object_literal.swift new file mode 100644 index 0000000..04d63b3 --- /dev/null +++ b/docs/tests/discouraged_object_literal.swift @@ -0,0 +1,11 @@ +//#Patterns: discouraged_object_literal + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "discouraged_object_literal"} +//#Issue: {"severity": "Warning", "line": 11, "patternId": "discouraged_object_literal"} + + + +let image = #imageLiteral(resourceName: "image.jpg") + + +let color = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1) diff --git a/docs/tests/dynamic_inline.swift b/docs/tests/dynamic_inline.swift new file mode 100644 index 0000000..81e7a2b --- /dev/null +++ b/docs/tests/dynamic_inline.swift @@ -0,0 +1,30 @@ +//#Patterns: dynamic_inline + +//#Issue: {"severity": "Error", "line": 10, "patternId": "dynamic_inline"} +//#Issue: {"severity": "Error", "line": 14, "patternId": "dynamic_inline"} +//#Issue: {"severity": "Error", "line": 18, "patternId": "dynamic_inline"} +//#Issue: {"severity": "Error", "line": 23, "patternId": "dynamic_inline"} +//#Issue: {"severity": "Error", "line": 29, "patternId": "dynamic_inline"} + +class C { +@inline(__always) dynamic func f() {} +} + +class C { +@inline(__always) public dynamic func f() {} +} + +class C { +@inline(__always) dynamic internal func f() {} +} + +class C { +@inline(__always) +dynamic func f() {} +} + +class C { +@inline(__always) +dynamic +func f() {} +} diff --git a/docs/tests/empty_count.swift b/docs/tests/empty_count.swift new file mode 100644 index 0000000..79138be --- /dev/null +++ b/docs/tests/empty_count.swift @@ -0,0 +1,32 @@ +//#Patterns: empty_count + +//#Issue: {"severity": "Error", "line": 14, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 16, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 18, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 20, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 22, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 24, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 26, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 28, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 30, "patternId": "empty_count"} +//#Issue: {"severity": "Error", "line": 32, "patternId": "empty_count"} + +[Int]().count == 0 + +0 == [Int]().count + +[Int]().count==0 + +[Int]().count > 0 + +[Int]().count != 0 + +[Int]().count == 0x0 + +[Int]().count == 0x00_00 + +[Int]().count == 0b00 + +[Int]().count == 0o00 + +count == 0 diff --git a/docs/tests/empty_parameters.swift b/docs/tests/empty_parameters.swift new file mode 100644 index 0000000..1827bdc --- /dev/null +++ b/docs/tests/empty_parameters.swift @@ -0,0 +1,17 @@ +//#Patterns: empty_parameters + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "empty_parameters"} +//#Issue: {"severity": "Warning", "line": 11, "patternId": "empty_parameters"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "empty_parameters"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "empty_parameters"} + + let abc: (Void) -> Void = {} + + + func foo(completion: (Void) -> Void) + + + func foo(completion: (Void) throws -> Void) + + + let foo: (Void) -> () throws -> Void) diff --git a/docs/tests/empty_parentheses_with_trailing_closure.swift b/docs/tests/empty_parentheses_with_trailing_closure.swift new file mode 100644 index 0000000..c2550f9 --- /dev/null +++ b/docs/tests/empty_parentheses_with_trailing_closure.swift @@ -0,0 +1,21 @@ +//#Patterns: empty_parentheses_with_trailing_closure + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "empty_parentheses_with_trailing_closure"} +//#Issue: {"severity": "Warning", "line": 11, "patternId": "empty_parentheses_with_trailing_closure"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "empty_parentheses_with_trailing_closure"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "empty_parentheses_with_trailing_closure"} + + [1, 2].map() { $0 + 1 } + + + [1, 2].map( ) { $0 + 1 } + + + [1, 2].map() { number in + number + 1 + } + + + [1, 2].map( ) { number in + number + 1 + } diff --git a/docs/tests/explicit_acl.swift b/docs/tests/explicit_acl.swift new file mode 100644 index 0000000..d52b98c --- /dev/null +++ b/docs/tests/explicit_acl.swift @@ -0,0 +1,27 @@ +//#Patterns: explicit_acl + +//#Issue: {"severity": "Warning", "line": 11, "patternId": "explicit_acl"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "explicit_acl"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "explicit_acl"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "explicit_acl"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "explicit_acl"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "explicit_acl"} + + +enum A {} + + +final class B {} + + +internal struct C { let d = 5 } + + +public struct C { let d = 5 } + + +func a() {} + + +internal let a = 0 +func b() {} diff --git a/docs/tests/explicit_enum_raw_value.swift b/docs/tests/explicit_enum_raw_value.swift new file mode 100644 index 0000000..b19b422 --- /dev/null +++ b/docs/tests/explicit_enum_raw_value.swift @@ -0,0 +1,38 @@ +//#Patterns: explicit_enum_raw_value + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "explicit_enum_raw_value"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "explicit_enum_raw_value"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "explicit_enum_raw_value"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "explicit_enum_raw_value"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "explicit_enum_raw_value"} +//#Issue: {"severity": "Warning", "line": 37, "patternId": "explicit_enum_raw_value"} + + +enum Numbers: Int { + case one = 10, two, three = 30 +} + + + +enum Numbers: NSInteger { + case one +} + + + +enum Numbers: String { + case one + case two +} + + + +enum Numbers: String { + case one, two = "two" +} + + + +enum Numbers: Decimal { + case one, ↓two +} diff --git a/docs/tests/explicit_init.swift b/docs/tests/explicit_init.swift new file mode 100644 index 0000000..0137361 --- /dev/null +++ b/docs/tests/explicit_init.swift @@ -0,0 +1,26 @@ +//#Patterns: explicit_init + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "explicit_init"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "explicit_init"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "explicit_init"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "explicit_init"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "explicit_init"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "explicit_init"} + +[1].flatMap{String.init($0)} + +[String.self].map { Type in Type.init(1) } + +func foo() -> [String] { + return [1].flatMap { String.init($0) } +} + +_ = GleanMetrics.Tabs.GroupedTabExtra.init() + +_ = Set.init() + +Observable.zip( + obs1, + obs2, + resultSelector: { MyType.init($0, $1) } +).asMaybe() diff --git a/docs/tests/explicit_top_level_acl.swift b/docs/tests/explicit_top_level_acl.swift new file mode 100644 index 0000000..9d36057 --- /dev/null +++ b/docs/tests/explicit_top_level_acl.swift @@ -0,0 +1,22 @@ +//#Patterns: explicit_top_level_acl + +//#Issue: {"severity": "Warning", "line": 9, "patternId": "explicit_top_level_acl"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "explicit_top_level_acl"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "explicit_top_level_acl"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "explicit_top_level_acl"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "explicit_top_level_acl"} + + enum A {} + + + final class B {} + + + struct C {} + + + func a() {} + + + internal let a = 0 + func b() {} diff --git a/docs/tests/explicit_type_interface.swift b/docs/tests/explicit_type_interface.swift new file mode 100644 index 0000000..49f17d8 --- /dev/null +++ b/docs/tests/explicit_type_interface.swift @@ -0,0 +1,27 @@ +//#Patterns: explicit_type_interface + +//#Issue: {"severity": "Warning", "line": 9, "patternId": "explicit_type_interface"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "explicit_type_interface"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "explicit_type_interface"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "explicit_type_interface"} + +class Foo { + var myVar = 0 + +} + + +class Foo { + let mylet = 0 + +} + + +class Foo { + static var myStaticVar = 0 +} + + +class Foo { + class var myClassVar = 0 +} diff --git a/docs/tests/fallthrough.swift b/docs/tests/fallthrough.swift new file mode 100644 index 0000000..a350526 --- /dev/null +++ b/docs/tests/fallthrough.swift @@ -0,0 +1,13 @@ +//#Patterns: fallthrough + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "fallthrough"} + + + +switch myvar { +case 1: + var a = 1 + fallthrough +case 2: + var a = 2 +} diff --git a/docs/tests/fatal_error_message.swift b/docs/tests/fatal_error_message.swift new file mode 100644 index 0000000..1a678e9 --- /dev/null +++ b/docs/tests/fatal_error_message.swift @@ -0,0 +1,13 @@ +//#Patterns: fatal_error_message + +//#Issue: {"severity": "Warning", "line": 7, "patternId": "fatal_error_message"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "fatal_error_message"} + + func foo() { + fatalError("") + } + + + func foo() { + fatalError() + } diff --git a/src/main/resources/docs/tests/file_length.swift b/docs/tests/file_length.swift similarity index 99% rename from src/main/resources/docs/tests/file_length.swift rename to docs/tests/file_length.swift index 0d5cd14..9f212b7 100644 --- a/src/main/resources/docs/tests/file_length.swift +++ b/docs/tests/file_length.swift @@ -1,6 +1,6 @@ //#Patterns: file_length -//#Issue: {"severity": "Info", "line": 808, "patternId": "file_length"} +//#Issue: {"severity": "Warning", "line": 808, "patternId": "file_length"} print("swiftlint") print("swiftlint") diff --git a/docs/tests/first_where.swift b/docs/tests/first_where.swift new file mode 100644 index 0000000..e812753 --- /dev/null +++ b/docs/tests/first_where.swift @@ -0,0 +1,30 @@ +//#Patterns: first_where + +//#Issue: {"severity": "Warning", "line": 13, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "first_where"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "first_where"} + +myList.filter { $0 % 2 == 0 }.first + +myList.filter({ $0 % 2 == 0 }).first + +myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first + +myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first?.something() + +myList.filter(someFunction).first + +myList.filter({ $0 % 2 == 0 }) +.first + +(myList.filter { $0 == 1 }).first + +myListOfDict.filter { dict in dict["1"] }.first + +myListOfDict.filter { $0["someString"] }.first diff --git a/src/main/resources/docs/tests/for_where.swift b/docs/tests/for_where.swift similarity index 56% rename from src/main/resources/docs/tests/for_where.swift rename to docs/tests/for_where.swift index 12b76e4..f7fdfae 100644 --- a/src/main/resources/docs/tests/for_where.swift +++ b/docs/tests/for_where.swift @@ -1,6 +1,6 @@ //#Patterns: for_where -//#Issue: {"severity": "Info", "line": 6, "patternId": "for_where"} +//#Issue: {"severity": "Warning", "line": 6, "patternId": "for_where"} for user in users { if user.id == 1 { return true } diff --git a/docs/tests/force_cast.swift b/docs/tests/force_cast.swift new file mode 100644 index 0000000..475cdf1 --- /dev/null +++ b/docs/tests/force_cast.swift @@ -0,0 +1,5 @@ +//#Patterns: force_cast + +//#Issue: {"severity": "Error", "line": 5, "patternId": "force_cast"} + +NSNumber() as! Int diff --git a/docs/tests/force_try.swift b/docs/tests/force_try.swift new file mode 100644 index 0000000..5e3ce92 --- /dev/null +++ b/docs/tests/force_try.swift @@ -0,0 +1,5 @@ +//#Patterns: force_try + +//#Issue: {"severity": "Error", "line": 5, "patternId": "force_try"} + +func a() throws {}; try! a() diff --git a/docs/tests/force_unwrapping.swift b/docs/tests/force_unwrapping.swift new file mode 100644 index 0000000..9010072 --- /dev/null +++ b/docs/tests/force_unwrapping.swift @@ -0,0 +1,43 @@ +//#Patterns: force_unwrapping + +//#Issue: {"severity": "Warning", "line": 17, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 37, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "force_unwrapping"} +//#Issue: {"severity": "Warning", "line": 43, "patternId": "force_unwrapping"} + + let url = NSURL(string: query)! + + navigationController!.pushViewController(viewController, animated: true) + + let unwrapped = optional! + + return cell! + + let url = NSURL(string: "http://www.google.com")! + + let dict = ["Boooo": "👻"]func bla() -> String { return dict["Boooo"]! } + + let dict = ["Boooo": "👻"]func bla() -> String { return dict["Boooo"]!.contains("B") } + + let a = dict["abc"]!.contains("B") + + dict["abc"]!.bar("B") + + if dict["a"]!!!! { + + var foo: [Bool]! = dict["abc"]! + + context("abc") { + var foo: [Bool]! = dict["abc"]! + } + + open var computed: String { return foo.bar! } diff --git a/src/main/resources/docs/tests/function_parameter_count.swift b/docs/tests/function_parameter_count.swift similarity index 53% rename from src/main/resources/docs/tests/function_parameter_count.swift rename to docs/tests/function_parameter_count.swift index c7febf2..9595234 100644 --- a/src/main/resources/docs/tests/function_parameter_count.swift +++ b/docs/tests/function_parameter_count.swift @@ -1,9 +1,9 @@ //#Patterns: function_parameter_count -//#Issue: {"severity": "Info", "line": 8, "patternId": "function_parameter_count"} -//#Issue: {"severity": "Info", "line": 10, "patternId": "function_parameter_count"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "function_parameter_count"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "function_parameter_count"} +//#Issue: {"severity": "Warning", "line": 8, "patternId": "function_parameter_count"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "function_parameter_count"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "function_parameter_count"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "function_parameter_count"} func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {} diff --git a/docs/tests/implicit_getter.swift b/docs/tests/implicit_getter.swift new file mode 100644 index 0000000..84fdfad --- /dev/null +++ b/docs/tests/implicit_getter.swift @@ -0,0 +1,58 @@ +//#Patterns: implicit_getter + +//#Issue: {"severity": "Warning", "line": 13, "patternId": "implicit_getter"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "implicit_getter"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "implicit_getter"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "implicit_getter"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "implicit_getter"} +//#Issue: {"severity": "Warning", "line": 48, "patternId": "implicit_getter"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "implicit_getter"} + +class Foo { + var foo: Int { + get { + return 20 + } + } +} + +class Foo { + var foo: Int { + get{ return 20 } + } +} + +class Foo { + static var foo: Int { + get { + return 20 + } + } +} + +var foo: Int { + get { return 20 } +} + +class Foo { + @objc func bar() {} + var foo: Int { + get { + return 20 + } + } +} + +extension Foo { + var bar: Bool { + get { _bar } + } +} + +class Foo { + subscript(i: Int) -> Int { + get { + return 20 + } + } +} diff --git a/docs/tests/is_disjoint.swift b/docs/tests/is_disjoint.swift new file mode 100644 index 0000000..7c7a22b --- /dev/null +++ b/docs/tests/is_disjoint.swift @@ -0,0 +1,11 @@ +//#Patterns: is_disjoint + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "is_disjoint"} +//#Issue: {"severity": "Warning", "line": 11, "patternId": "is_disjoint"} + + + +_ = Set(syntaxKinds).intersection(commentAndStringKindsSet).isEmpty + + +let isObjc = !objcAttributes.intersection(dictionary.enclosedSwiftAttributes).isEmpty diff --git a/docs/tests/joined_default_parameter.swift b/docs/tests/joined_default_parameter.swift new file mode 100644 index 0000000..e45748f --- /dev/null +++ b/docs/tests/joined_default_parameter.swift @@ -0,0 +1,12 @@ +//#Patterns: joined_default_parameter + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "joined_default_parameter"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "joined_default_parameter"} + + + +let foo = bar.joined(separator: "") + + +let foo = bar.filter(toto) + .joined(separator: "") diff --git a/docs/tests/legacy_cggeometry_functions.swift b/docs/tests/legacy_cggeometry_functions.swift new file mode 100644 index 0000000..a8a2b85 --- /dev/null +++ b/docs/tests/legacy_cggeometry_functions.swift @@ -0,0 +1,62 @@ +//#Patterns: legacy_cggeometry_functions + +//#Issue: {"severity": "Warning", "line": 24, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 36, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 46, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 48, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 50, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 52, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 56, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 58, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 60, "patternId": "legacy_cggeometry_functions"} +//#Issue: {"severity": "Warning", "line": 62, "patternId": "legacy_cggeometry_functions"} + + CGRectGetWidth(rect) + + CGRectGetHeight(rect) + + CGRectGetMinX(rect) + + CGRectGetMidX(rect) + + CGRectGetMaxX(rect) + + CGRectGetMinY(rect) + + CGRectGetMidY(rect) + + CGRectGetMaxY(rect) + + CGRectIsNull(rect) + + CGRectIsEmpty(rect) + + CGRectIsInfinite(rect) + + CGRectStandardize(rect) + + CGRectIntegral(rect) + + CGRectInset(rect, 10, 5) + + CGRectOffset(rect, -2, 8.3) + + CGRectUnion(rect1, rect2) + + CGRectIntersection(rect1, rect2) + + CGRectContainsRect(rect1, rect2) + + CGRectContainsPoint(rect, point) + + CGRectIntersectsRect(rect1, rect2) diff --git a/docs/tests/legacy_constant.swift b/docs/tests/legacy_constant.swift new file mode 100644 index 0000000..cd0727e --- /dev/null +++ b/docs/tests/legacy_constant.swift @@ -0,0 +1,32 @@ +//#Patterns: legacy_constant + +//#Issue: {"severity": "Warning", "line": 14, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "legacy_constant"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "legacy_constant"} + + CGRectInfinite + + CGPointZero + + CGRectZero + + CGSizeZero + + NSZeroPoint + + NSZeroRect + + NSZeroSize + + CGRectNull + + CGFloat(M_PI) + + Float(M_PI) diff --git a/docs/tests/legacy_constructor.swift b/docs/tests/legacy_constructor.swift new file mode 100644 index 0000000..3ce126c --- /dev/null +++ b/docs/tests/legacy_constructor.swift @@ -0,0 +1,62 @@ +//#Patterns: legacy_constructor + +//#Issue: {"severity": "Warning", "line": 24, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 36, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 46, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 48, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 50, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 52, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 56, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 58, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 60, "patternId": "legacy_constructor"} +//#Issue: {"severity": "Warning", "line": 62, "patternId": "legacy_constructor"} + + CGPointMake(10, 10) + + CGPointMake(xVal, yVal) + + CGSizeMake(10, 10) + + CGSizeMake(aWidth, aHeight) + + CGRectMake(0, 0, 10, 10) + + CGRectMake(xVal, yVal, width, height) + + CGVectorMake(10, 10) + + CGVectorMake(deltaX, deltaY) + + NSMakePoint(10, 10) + + NSMakePoint(xVal, yVal) + + NSMakeSize(10, 10) + + NSMakeSize(aWidth, aHeight) + + NSMakeRect(0, 0, 10, 10) + + NSMakeRect(xVal, yVal, width, height) + + NSMakeRange(10, 1) + + NSMakeRange(loc, len) + + UIEdgeInsetsMake(0, 0, 10, 10) + + UIEdgeInsetsMake(top, left, bottom, right) + + NSEdgeInsetsMake(0, 0, 10, 10) + + NSEdgeInsetsMake(top, left, bottom, right) diff --git a/docs/tests/legacy_nsgeometry_functions.swift b/docs/tests/legacy_nsgeometry_functions.swift new file mode 100644 index 0000000..83d57e1 --- /dev/null +++ b/docs/tests/legacy_nsgeometry_functions.swift @@ -0,0 +1,65 @@ +//#Patterns: legacy_nsgeometry_functions + +//#Issue: {"severity": "Warning", "line": 25, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 37, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 39, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 41, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 43, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 45, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 47, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 49, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 51, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 53, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 55, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 57, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 59, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 61, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 63, "patternId": "legacy_nsgeometry_functions"} +//#Issue: {"severity": "Warning", "line": 65, "patternId": "legacy_nsgeometry_functions"} + + NSWidth(rect) + + NSHeight(rect) + + NSMinX(rect) + + NSMidX(rect) + + NSMaxX(rect) + + NSMinY(rect) + + NSMidY(rect) + + NSMaxY(rect) + + NSEqualRects(rect1, rect2) + + NSEqualSizes(size1, size2) + + NSEqualPoints(point1, point2) + + NSEdgeInsetsEqual(insets2, insets2) + + NSIsEmptyRect(rect) + + NSIntegralRect(rect) + + NSInsetRect(rect, 10, 5) + + NSOffsetRect(rect, -2, 8.3) + + NSUnionRect(rect1, rect2) + + NSIntersectionRect(rect1, rect2) + + NSContainsRect(rect1, rect2) + + NSPointInRect(rect, point) + + NSIntersectsRect(rect1, rect2) diff --git a/docs/tests/let_var_whitespace.swift b/docs/tests/let_var_whitespace.swift new file mode 100644 index 0000000..ffe7a46 --- /dev/null +++ b/docs/tests/let_var_whitespace.swift @@ -0,0 +1,42 @@ +//#Patterns: let_var_whitespace + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "let_var_whitespace"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "let_var_whitespace"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "let_var_whitespace"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "let_var_whitespace"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "let_var_whitespace"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "let_var_whitespace"} + + +var x = 1 +x = 2 + + + + +a = 5 +var x = 1 + + + +struct X { + let a + func x() {} +} + + + +var x = 0 +@objc func f() {} + + + +var x = 0 +@objc +func f() {} + + + +@objc func f() { +} +var x = 0 diff --git a/src/main/resources/docs/tests/line_length.swift b/docs/tests/line_length.swift similarity index 98% rename from src/main/resources/docs/tests/line_length.swift rename to docs/tests/line_length.swift index c660465..3aeafb7 100644 --- a/src/main/resources/docs/tests/line_length.swift +++ b/docs/tests/line_length.swift @@ -1,8 +1,8 @@ //#Patterns: line_length -//#Issue: {"severity": "Info", "line": 7, "patternId": "line_length"} -//#Issue: {"severity": "Info", "line": 10, "patternId": "line_length"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "line_length"} +//#Issue: {"severity": "Warning", "line": 7, "patternId": "line_length"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "line_length"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "line_length"} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/docs/tests/literal_expression_end_indentation.swift b/docs/tests/literal_expression_end_indentation.swift new file mode 100644 index 0000000..dd09645 --- /dev/null +++ b/docs/tests/literal_expression_end_indentation.swift @@ -0,0 +1,25 @@ +//#Patterns: literal_expression_end_indentation + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "literal_expression_end_indentation"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "literal_expression_end_indentation"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "literal_expression_end_indentation"} + + + +let x = [ + 1, + 2 + ] + +Example #2 + + let x = [ + 1, + 2 +] + +Example #3 + +let x = [ + key: value + ] diff --git a/docs/tests/mark.swift b/docs/tests/mark.swift new file mode 100644 index 0000000..146ba6b --- /dev/null +++ b/docs/tests/mark.swift @@ -0,0 +1,62 @@ +//#Patterns: mark + +//#Issue: {"severity": "Warning", "line": 24, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 36, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 46, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 48, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 50, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 52, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 56, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 58, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 59, "patternId": "mark"} +//#Issue: {"severity": "Warning", "line": 61, "patternId": "mark"} + + //MARK: bad + + // MARK:bad + + //MARK:bad + + // MARK: bad + + // MARK: bad + + // MARK: -bad + + // MARK:- bad + + // MARK:-bad + + //MARK: - bad + + //MARK:- bad + + //MARK: -bad + + //MARK:-bad + + //Mark: bad + + // Mark: bad + + // MARK bad + + //MARK bad + + // MARK - bad + + //MARK:- Top-Level bad mark + //MARK:- Another bad mark + struct MarkTest {} + // MARK:- Bad mark + extension MarkTest {} diff --git a/docs/tests/multiline_arguments.swift b/docs/tests/multiline_arguments.swift new file mode 100644 index 0000000..d528bbe --- /dev/null +++ b/docs/tests/multiline_arguments.swift @@ -0,0 +1,27 @@ +//#Patterns: multiline_arguments + +//#Issue: {"severity": "Warning", "line": 13, "patternId": "multiline_arguments"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "multiline_arguments"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "multiline_arguments"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "multiline_arguments"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "multiline_arguments"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "multiline_arguments"} + + + +foo(0, + param1: 1, param2: true, param3: [3]) + + +foo(0, param1: 1, + param2: true, param3: [3]) + + +foo(0, param1: 1, param2: true, + param3: [3]) + + +foo( + 0, param1: 1, + param2: true, param3: [3] +) diff --git a/docs/tests/multiple_closures_with_trailing_closure.swift b/docs/tests/multiple_closures_with_trailing_closure.swift new file mode 100644 index 0000000..563a950 --- /dev/null +++ b/docs/tests/multiple_closures_with_trailing_closure.swift @@ -0,0 +1,15 @@ +//#Patterns: multiple_closures_with_trailing_closure + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "multiple_closures_with_trailing_closure"} +//#Issue: {"severity": "Warning", "line": 13, "patternId": "multiple_closures_with_trailing_closure"} + + + +foo.something(param1: { $0 }) { $0 + 1 } + + +UIView.animate(withDuration: 1.0, animations: { + someView.alpha = 0.0 +}) { _ in + someView.removeFromSuperview() +} diff --git a/docs/tests/nesting.swift b/docs/tests/nesting.swift new file mode 100644 index 0000000..e095436 --- /dev/null +++ b/docs/tests/nesting.swift @@ -0,0 +1,31 @@ +//#Patterns: nesting + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "nesting"} +//#Issue: {"severity": "Warning", "line": 13, "patternId": "nesting"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "nesting"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "nesting"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "nesting"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "nesting"} + + class A { class B { class C {} } } + + + struct A { struct B { struct C {} } } + + + enum A { enum B { enum C {} } } + + + func func0() { + func func1() { + func func2() { + func func3() { + func func4() { func func5() { + func func6() { + } + } + } + } + } + } + } diff --git a/docs/tests/nimble_operator.swift b/docs/tests/nimble_operator.swift new file mode 100644 index 0000000..cd51956 --- /dev/null +++ b/docs/tests/nimble_operator.swift @@ -0,0 +1,38 @@ +//#Patterns: nimble_operator + +//#Issue: {"severity": "Warning", "line": 13, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "nimble_operator"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "nimble_operator"} + + expect(seagull.squawk).toNot(equal("Hi")) + + + expect(12).toNot(equal(10)) + + + expect(10).to(equal(10)) + + + expect(10).to(beGreaterThan(8)) + + + expect(10).to(beGreaterThanOrEqualTo(10)) + + + expect(10).to(beLessThan(11)) + + + expect(10).to(beLessThanOrEqualTo(10)) + + + expect(x).to(beIdenticalTo(x)) + + + expect(10) > 2 + expect(10).to(beGreaterThan(2)) diff --git a/docs/tests/no_extension_access_modifier.swift b/docs/tests/no_extension_access_modifier.swift new file mode 100644 index 0000000..b584468 --- /dev/null +++ b/docs/tests/no_extension_access_modifier.swift @@ -0,0 +1,18 @@ +//#Patterns: no_extension_access_modifier + +//#Issue: {"severity": "Error", "line": 9, "patternId": "no_extension_access_modifier"} +//#Issue: {"severity": "Error", "line": 11, "patternId": "no_extension_access_modifier"} +//#Issue: {"severity": "Error", "line": 14, "patternId": "no_extension_access_modifier"} +//#Issue: {"severity": "Error", "line": 16, "patternId": "no_extension_access_modifier"} +//#Issue: {"severity": "Error", "line": 18, "patternId": "no_extension_access_modifier"} + +private extension String {} + +public + extension String {} + +open extension String {} + +internal extension String {} + +fileprivate extension String {} diff --git a/docs/tests/no_grouping_extension.swift b/docs/tests/no_grouping_extension.swift new file mode 100644 index 0000000..ec71e66 --- /dev/null +++ b/docs/tests/no_grouping_extension.swift @@ -0,0 +1,26 @@ +//#Patterns: no_grouping_extension + +//#Issue: {"severity": "Warning", "line": 11, "patternId": "no_grouping_extension"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "no_grouping_extension"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "no_grouping_extension"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "no_grouping_extension"} + + + +enum Fruit {} +extension Fruit {} + + + +extension Tea: Error {} +struct Tea {} + + + +class Ham { class Spam {}} +extension Ham.Spam {} + + + +extension External { struct Gotcha {}} +extension External.Gotcha {} diff --git a/src/main/resources/docs/tests/notification_center_detachment.swift b/docs/tests/notification_center_detachment.swift similarity index 62% rename from src/main/resources/docs/tests/notification_center_detachment.swift rename to docs/tests/notification_center_detachment.swift index 14a4779..a0964c8 100644 --- a/src/main/resources/docs/tests/notification_center_detachment.swift +++ b/docs/tests/notification_center_detachment.swift @@ -1,6 +1,6 @@ //#Patterns: notification_center_detachment -//#Issue: {"severity": "Info", "line": 7, "patternId": "notification_center_detachment"} +//#Issue: {"severity": "Warning", "line": 7, "patternId": "notification_center_detachment"} class Foo { func bar() { diff --git a/docs/tests/object_literal.swift b/docs/tests/object_literal.swift new file mode 100644 index 0000000..ce35dd2 --- /dev/null +++ b/docs/tests/object_literal.swift @@ -0,0 +1,50 @@ +//#Patterns: object_literal + +//#Issue: {"severity": "Warning", "line": 20, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 36, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 46, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 48, "patternId": "object_literal"} +//#Issue: {"severity": "Warning", "line": 50, "patternId": "object_literal"} + + let image = UIImage(named: "foo") + + let color = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) + + let color = UIColor(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) + + let color = UIColor(white: 0.5, alpha: 1) + + let image = NSImage(named: "foo") + + let color = NSColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) + + let color = NSColor(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) + + let color = NSColor(white: 0.5, alpha: 1) + + let image = UIImage.init(named: "foo") + + let color = UIColor.init(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) + + let color = UIColor.init(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) + + let color = UIColor.init(white: 0.5, alpha: 1) + + let image = NSImage.init(named: "foo") + + let color = NSColor.init(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) + + let color = NSColor.init(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) + + let color = NSColor.init(white: 0.5, alpha: 1) diff --git a/docs/tests/operator_whitespace.swift b/docs/tests/operator_whitespace.swift new file mode 100644 index 0000000..7bbc866 --- /dev/null +++ b/docs/tests/operator_whitespace.swift @@ -0,0 +1,20 @@ +//#Patterns: operator_whitespace + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "operator_whitespace"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "operator_whitespace"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "operator_whitespace"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "operator_whitespace"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "operator_whitespace"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "operator_whitespace"} + +func <|(lhs: Int, rhs: Int) -> Int {} + +func <|<
(lhs: A, rhs: A) -> A {} + +func <| (lhs: Int, rhs: Int) -> Int {} + +func <|< (lhs: A, rhs: A) -> A {} + +func <| (lhs: Int, rhs: Int) -> Int {} + +func <|< (lhs: A, rhs: A) -> A {} diff --git a/src/main/resources/docs/tests/overridden_super_call.swift b/docs/tests/overridden_super_call.swift similarity index 65% rename from src/main/resources/docs/tests/overridden_super_call.swift rename to docs/tests/overridden_super_call.swift index 72895a3..5ae97bc 100644 --- a/src/main/resources/docs/tests/overridden_super_call.swift +++ b/docs/tests/overridden_super_call.swift @@ -1,8 +1,8 @@ //#Patterns: overridden_super_call -//#Issue: {"severity": "Info", "line": 8, "patternId": "overridden_super_call"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "overridden_super_call"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "overridden_super_call"} +//#Issue: {"severity": "Warning", "line": 8, "patternId": "overridden_super_call"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "overridden_super_call"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "overridden_super_call"} class VC: UIViewController { override func viewWillAppear(_ animated: Bool) { diff --git a/docs/tests/override_in_extension.swift b/docs/tests/override_in_extension.swift new file mode 100644 index 0000000..23c84aa --- /dev/null +++ b/docs/tests/override_in_extension.swift @@ -0,0 +1,16 @@ +//#Patterns: override_in_extension + +//#Issue: {"severity": "Warning", "line": 9, "patternId": "override_in_extension"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "override_in_extension"} + + + +extension Person { + override var age: Int { return 42 } +} + + + +extension Person { + override func celebrateBirthday() {} +} diff --git a/docs/tests/pattern_matching_keywords.swift b/docs/tests/pattern_matching_keywords.swift new file mode 100644 index 0000000..c6676d5 --- /dev/null +++ b/docs/tests/pattern_matching_keywords.swift @@ -0,0 +1,37 @@ +//#Patterns: pattern_matching_keywords + +//#Issue: {"severity": "Warning", "line": 11, "patternId": "pattern_matching_keywords"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "pattern_matching_keywords"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "pattern_matching_keywords"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "pattern_matching_keywords"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "pattern_matching_keywords"} +//#Issue: {"severity": "Warning", "line": 36, "patternId": "pattern_matching_keywords"} + +switch foo { +case (let x, let y): break +} + + +switch foo { +case .foo(let x, let y): break +} + + +switch foo { +case (.yamlParsing(let x), .yamlParsing(let y)): break +} + + +switch foo { +case (var x, var y): break +} + + +switch foo { +case .foo(var x, var y): break +} + + +switch foo { +case (.yamlParsing(var x), .yamlParsing(var y)): break +} diff --git a/docs/tests/private_action.swift b/docs/tests/private_action.swift new file mode 100644 index 0000000..a8caaaa --- /dev/null +++ b/docs/tests/private_action.swift @@ -0,0 +1,78 @@ +//#Patterns: private_action + +//#Issue: {"severity": "Warning", "line": 17, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 41, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 47, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 53, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 59, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 65, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 71, "patternId": "private_action"} +//#Issue: {"severity": "Warning", "line": 77, "patternId": "private_action"} + + +class Foo { + @IBAction func barButtonTapped(_ sender: UIButton) {} +} + + + +struct Foo { + @IBAction func barButtonTapped(_ sender: UIButton) {} +} + + + +class Foo { + @IBAction public func barButtonTapped(_ sender: UIButton) {} +} + + + +struct Foo { + @IBAction public func barButtonTapped(_ sender: UIButton) {} +} + + + +class Foo { + @IBAction internal func barButtonTapped(_ sender: UIButton) {} +} + + + +struct Foo { + @IBAction internal func barButtonTapped(_ sender: UIButton) {} +} + + + +extension Foo { + @IBAction func barButtonTapped(_ sender: UIButton) {} +} + + + +extension Foo { + @IBAction public func barButtonTapped(_ sender: UIButton) {} +} + + + +extension Foo { + @IBAction internal func barButtonTapped(_ sender: UIButton) {} +} + + + +public extension Foo { + @IBAction func barButtonTapped(_ sender: UIButton) {} +} + + + +internal extension Foo { + @IBAction func barButtonTapped(_ sender: UIButton) {} +} diff --git a/docs/tests/private_outlet.swift b/docs/tests/private_outlet.swift new file mode 100644 index 0000000..fed5029 --- /dev/null +++ b/docs/tests/private_outlet.swift @@ -0,0 +1,13 @@ +//#Patterns: private_outlet + +//#Issue: {"severity": "Warning", "line": 7, "patternId": "private_outlet"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "private_outlet"} + + class Foo { + @IBOutlet var label: UILabel? + } + + + class Foo { + @IBOutlet var label: UILabel! + } diff --git a/docs/tests/private_over_fileprivate.swift b/docs/tests/private_over_fileprivate.swift new file mode 100644 index 0000000..7e9e48e --- /dev/null +++ b/docs/tests/private_over_fileprivate.swift @@ -0,0 +1,12 @@ +//#Patterns: private_over_fileprivate + +//#Issue: {"severity": "Warning", "line": 7, "patternId": "private_over_fileprivate"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "private_over_fileprivate"} + + +fileprivate enum MyEnum {} + + +fileprivate class MyClass { + fileprivate(set) var myInt = 4 +} diff --git a/src/main/resources/docs/tests/private_unit_test.swift b/docs/tests/private_unit_test.swift similarity index 66% rename from src/main/resources/docs/tests/private_unit_test.swift rename to docs/tests/private_unit_test.swift index 657213c..35f9550 100644 --- a/src/main/resources/docs/tests/private_unit_test.swift +++ b/docs/tests/private_unit_test.swift @@ -1,9 +1,9 @@ //#Patterns: private_unit_test -//#Issue: {"severity": "Info", "line": 8, "patternId": "private_unit_test"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "private_unit_test"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "private_unit_test"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "private_unit_test"} +//#Issue: {"severity": "Warning", "line": 8, "patternId": "private_unit_test"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "private_unit_test"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "private_unit_test"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "private_unit_test"} private class FooTest: XCTestCase { func test1() {} internal func test2() {} diff --git a/src/main/resources/docs/tests/prohibited_super_call.swift b/docs/tests/prohibited_super_call.swift similarity index 66% rename from src/main/resources/docs/tests/prohibited_super_call.swift rename to docs/tests/prohibited_super_call.swift index 26c08ec..d879a60 100644 --- a/src/main/resources/docs/tests/prohibited_super_call.swift +++ b/docs/tests/prohibited_super_call.swift @@ -1,9 +1,9 @@ //#Patterns: prohibited_super_call -//#Issue: {"severity": "Info", "line": 9, "patternId": "prohibited_super_call"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "prohibited_super_call"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "prohibited_super_call"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "prohibited_super_call"} +//#Issue: {"severity": "Warning", "line": 9, "patternId": "prohibited_super_call"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "prohibited_super_call"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "prohibited_super_call"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "prohibited_super_call"} class VC: UIViewController { override func loadView() { diff --git a/src/main/resources/docs/tests/protocol_property_accessors_order.swift b/docs/tests/protocol_property_accessors_order.swift similarity index 53% rename from src/main/resources/docs/tests/protocol_property_accessors_order.swift rename to docs/tests/protocol_property_accessors_order.swift index 6836af9..1dec6da 100644 --- a/src/main/resources/docs/tests/protocol_property_accessors_order.swift +++ b/docs/tests/protocol_property_accessors_order.swift @@ -1,6 +1,6 @@ //#Patterns: protocol_property_accessors_order -//#Issue: {"severity": "Info", "line": 6, "patternId": "protocol_property_accessors_order"} +//#Issue: {"severity": "Warning", "line": 6, "patternId": "protocol_property_accessors_order"} protocol Foo { var bar: String { set get } diff --git a/docs/tests/quick_discouraged_call.swift b/docs/tests/quick_discouraged_call.swift new file mode 100644 index 0000000..3963cc2 --- /dev/null +++ b/docs/tests/quick_discouraged_call.swift @@ -0,0 +1,161 @@ +//#Patterns: quick_discouraged_call + +//#Issue: {"severity": "Warning", "line": 30, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 51, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 55, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 79, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 92, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 102, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 112, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 122, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 132, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 142, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 145, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 155, "patternId": "quick_discouraged_call"} +//#Issue: {"severity": "Warning", "line": 158, "patternId": "quick_discouraged_call"} + + +class TotoTests { + override func spec() { + describe("foo") { + let foo = Foo() + } + } +} +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + let foo = Foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + let foo = Foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + context("foo") { + let foo = Foo() + } + context("bar") { + let foo = Foo() + foo.bar() + it("does something") { + let foo = Foo() + foo.toto() + } + } + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + context("foo") { + context("foo") { + beforeEach { + let foo = Foo() + foo.toto() + } + it("bar") { + } + context("foo") { + let foo = Foo() + } + } + } + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + let foo = Foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + sharedExamples("foo") { + let foo = Foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + sharedExamples("foo") { + foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + xdescribe("foo") { + let foo = Foo() + } + fdescribe("foo") { + let foo = Foo() + } + } +} + + + +class TotoTests: QuickSpec { + override func spec() { + xcontext("foo") { + let foo = Foo() + } + fcontext("foo") { + let foo = Foo() + } + } +} diff --git a/docs/tests/quick_discouraged_focused_test.swift b/docs/tests/quick_discouraged_focused_test.swift new file mode 100644 index 0000000..5746c17 --- /dev/null +++ b/docs/tests/quick_discouraged_focused_test.swift @@ -0,0 +1,65 @@ +//#Patterns: quick_discouraged_focused_test + +//#Issue: {"severity": "Warning", "line": 13, "patternId": "quick_discouraged_focused_test"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "quick_discouraged_focused_test"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "quick_discouraged_focused_test"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "quick_discouraged_focused_test"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "quick_discouraged_focused_test"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "quick_discouraged_focused_test"} +//#Issue: {"severity": "Warning", "line": 63, "patternId": "quick_discouraged_focused_test"} + +class TotoTests: QuickSpec { + override func spec() { + fdescribe("foo") { } + } +} + + +class TotoTests: QuickSpec { + override func spec() { + fcontext("foo") { } + } +} + + +class TotoTests: QuickSpec { + override func spec() { + fit("foo") { } + } +} + + +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + fit("bar") { } + } + } +} + + +class TotoTests: QuickSpec { + override func spec() { + context("foo") { + fit("bar") { } + } + } +} + + +class TotoTests: QuickSpec { + override func spec() { + describe("foo") { + context("bar") { + fit("toto") { } + } + } + } +} + + +class TotoTests: QuickSpec { + override func spec() { + fitBehavesLike("foo") + } +} diff --git a/docs/tests/redundant_optional_initialization.swift b/docs/tests/redundant_optional_initialization.swift new file mode 100644 index 0000000..69c122f --- /dev/null +++ b/docs/tests/redundant_optional_initialization.swift @@ -0,0 +1,17 @@ +//#Patterns: redundant_optional_initialization + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "redundant_optional_initialization"} +//#Issue: {"severity": "Warning", "line": 11, "patternId": "redundant_optional_initialization"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "redundant_optional_initialization"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "redundant_optional_initialization"} + + var myVar: Int? = nil + + + var myVar: Optional = nil + + + var myVar: Int?=nil + + + var myVar: Optional=nil diff --git a/docs/tests/redundant_void_return.swift b/docs/tests/redundant_void_return.swift new file mode 100644 index 0000000..f5e239f --- /dev/null +++ b/docs/tests/redundant_void_return.swift @@ -0,0 +1,21 @@ +//#Patterns: redundant_void_return + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "redundant_void_return"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "redundant_void_return"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "redundant_void_return"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "redundant_void_return"} + + func foo() -> Void {} + + + protocol Foo { + func foo() -> Void + } + + + func foo() -> () {} + + + protocol Foo { + func foo() -> () + } diff --git a/docs/tests/required_enum_case.swift b/docs/tests/required_enum_case.swift new file mode 100644 index 0000000..afa4677 --- /dev/null +++ b/docs/tests/required_enum_case.swift @@ -0,0 +1,23 @@ +//#Patterns: required_enum_case + + +enum MyNetworkResponse: String, NetworkResponsable { + case success, error +} + + +enum MyNetworkResponse: String, NetworkResponsable { + case success, error +} + + +enum MyNetworkResponse: String, NetworkResponsable { + case success + case error +} + + +enum MyNetworkResponse: String, NetworkResponsable { + case success + case error +} diff --git a/docs/tests/return_arrow_whitespace.swift b/docs/tests/return_arrow_whitespace.swift new file mode 100644 index 0000000..2c4b840 --- /dev/null +++ b/docs/tests/return_arrow_whitespace.swift @@ -0,0 +1,33 @@ +//#Patterns: return_arrow_whitespace + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "return_arrow_whitespace"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "return_arrow_whitespace"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "return_arrow_whitespace"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "return_arrow_whitespace"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "return_arrow_whitespace"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "return_arrow_whitespace"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "return_arrow_whitespace"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "return_arrow_whitespace"} + + func abc()->Int {} + + + func abc()->[Int] {} + + + func abc()->(Int, Int) {} + + + func abc()-> Int {} + + + func abc() ->Int {} + + + func abc() -> Int {} + + + var abc = {(param: Int) ->Bool in } + + + var abc = {(param: Int)->Bool in } diff --git a/docs/tests/scriptFile.scala b/docs/tests/scriptFile.scala new file mode 100644 index 0000000..6ce71f7 --- /dev/null +++ b/docs/tests/scriptFile.scala @@ -0,0 +1 @@ +closure_end_indentation \ No newline at end of file diff --git a/docs/tests/shorthand_operator.swift b/docs/tests/shorthand_operator.swift new file mode 100644 index 0000000..9a879b6 --- /dev/null +++ b/docs/tests/shorthand_operator.swift @@ -0,0 +1,88 @@ +//#Patterns: shorthand_operator + +//#Issue: {"severity": "Error", "line": 26, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 29, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 32, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 35, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 38, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 41, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 44, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 47, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 50, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 53, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 56, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 59, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 62, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 65, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 68, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 71, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 74, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 77, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 80, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 83, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 86, "patternId": "shorthand_operator"} +//#Issue: {"severity": "Error", "line": 88, "patternId": "shorthand_operator"} + +foo = foo - 1 + + +foo = foo - aVariable + + +foo = foo - bar.method() + + +foo.aProperty = foo.aProperty - 1 + + +self.aProperty = self.aProperty - 1 + + +foo = foo / 1 + + +foo = foo / aVariable + + +foo = foo / bar.method() + + +foo.aProperty = foo.aProperty / 1 + + +self.aProperty = self.aProperty / 1 + + +foo = foo + 1 + + +foo = foo + aVariable + + +foo = foo + bar.method() + + +foo.aProperty = foo.aProperty + 1 + + +self.aProperty = self.aProperty + 1 + + +foo = foo * 1 + + +foo = foo * aVariable + + +foo = foo * bar.method() + + +foo.aProperty = foo.aProperty * 1 + + +self.aProperty = self.aProperty * 1 + + +n = n + i / outputLength + +n = n - i / outputLength diff --git a/docs/tests/sorted_first_last.swift b/docs/tests/sorted_first_last.swift new file mode 100644 index 0000000..47dddad --- /dev/null +++ b/docs/tests/sorted_first_last.swift @@ -0,0 +1,66 @@ +//#Patterns: sorted_first_last + +//#Issue: {"severity": "Warning", "line": 18, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 46, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 50, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 58, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 62, "patternId": "sorted_first_last"} +//#Issue: {"severity": "Warning", "line": 66, "patternId": "sorted_first_last"} + + +myList.sorted().first + + + +myList.sorted(by: { $0.description < $1.description }).first + + + +myList.sorted(by: >).first + + + +myList.map { $0 + 1 }.sorted().first + + + +myList.sorted(by: someFunction).first + + + +myList.map { $0 + 1 }.sorted { $0.description < $1.description }.first + + + +myList.sorted().last + + + +myList.sorted().last?.something() + + + +myList.sorted(by: { $0.description < $1.description }).last + + + +myList.map { $0 + 1 }.sorted().last + + + +myList.sorted(by: someFunction).last + + + +myList.map { $0 + 1 }.sorted { $0.description < $1.description }.last + + + +myList.map { $0 + 1 }.sorted { $0.first < $1.first }.last diff --git a/src/main/resources/docs/tests/sorted_imports.swift b/docs/tests/sorted_imports.swift similarity index 54% rename from src/main/resources/docs/tests/sorted_imports.swift rename to docs/tests/sorted_imports.swift index fc3e85e..b57199a 100644 --- a/src/main/resources/docs/tests/sorted_imports.swift +++ b/docs/tests/sorted_imports.swift @@ -1,6 +1,6 @@ //#Patterns: sorted_imports -//#Issue: {"severity": "Info", "line": 7, "patternId": "sorted_imports"} +//#Issue: {"severity": "Warning", "line": 7, "patternId": "sorted_imports"} import AAA import ZZZ diff --git a/docs/tests/statement_position.swift b/docs/tests/statement_position.swift new file mode 100644 index 0000000..7def736 --- /dev/null +++ b/docs/tests/statement_position.swift @@ -0,0 +1,19 @@ +//#Patterns: statement_position + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "statement_position"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "statement_position"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "statement_position"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "statement_position"} + +if { + +↓}else if { + +↓} else { + +↓} +catch { + +↓} + catch { +} diff --git a/docs/tests/strict_fileprivate.swift b/docs/tests/strict_fileprivate.swift new file mode 100644 index 0000000..89ae6a6 --- /dev/null +++ b/docs/tests/strict_fileprivate.swift @@ -0,0 +1,33 @@ +//#Patterns: strict_fileprivate + +//#Issue: {"severity": "Warning", "line": 13, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "strict_fileprivate"} +//#Issue: {"severity": "Warning", "line": 31, "patternId": "strict_fileprivate"} + + fileprivate class C { + fileprivate func f() {} + } + + fileprivate extension String { + fileprivate var isSomething: Bool { self == "something" } + } + + fileprivate actor A { + fileprivate let i = 1 + } + + fileprivate struct C { + fileprivate(set) var myInt = 4 + } + + struct Outter { + struct Inter { + fileprivate struct Inner {} + } + } diff --git a/docs/tests/superfluous_disable_command.swift b/docs/tests/superfluous_disable_command.swift new file mode 100644 index 0000000..e1bc6dd --- /dev/null +++ b/docs/tests/superfluous_disable_command.swift @@ -0,0 +1 @@ +//#Patterns: superfluous_disable_command diff --git a/docs/tests/switch_case_alignment.swift b/docs/tests/switch_case_alignment.swift new file mode 100644 index 0000000..f71880c --- /dev/null +++ b/docs/tests/switch_case_alignment.swift @@ -0,0 +1,34 @@ +//#Patterns: switch_case_alignment + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "switch_case_alignment"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "switch_case_alignment"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "switch_case_alignment"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "switch_case_alignment"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "switch_case_alignment"} + + + + switch someBool { + case true: + print('red') + case false: + print('blue') + } + + if aBool { + switch someBool { + case true: + print('red') + case false: + print('blue') + } + } + + switch someInt { + case 0: + print('Zero') + case 1: + print('One') + default: + print('Some other number') + } diff --git a/docs/tests/switch_case_on_newline.swift b/docs/tests/switch_case_on_newline.swift new file mode 100644 index 0000000..070f7ae --- /dev/null +++ b/docs/tests/switch_case_on_newline.swift @@ -0,0 +1,58 @@ +//#Patterns: switch_case_on_newline + +//#Issue: {"severity": "Warning", "line": 14, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 39, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 50, "patternId": "switch_case_on_newline"} +//#Issue: {"severity": "Warning", "line": 56, "patternId": "switch_case_on_newline"} + + switch foo { + case 1: return true + } + + + switch foo { + case let value: return true + } + + + switch foo { + default: return true + } + + + switch foo { + case "a string": return false + } + + + switch foo { + case .myCase: return false // error from network + } + + + switch foo { + case let .myCase(value) where value > 10: return false + } + + + switch foo { + case #selector(aFunction(_:)): return false + + } + + + switch foo { + case let .myCase(value) + where value > 10: return false + } + + + switch foo { + case .first, + .second: return false + } diff --git a/docs/tests/todo.swift b/docs/tests/todo.swift new file mode 100644 index 0000000..380b461 --- /dev/null +++ b/docs/tests/todo.swift @@ -0,0 +1,33 @@ +//#Patterns: todo + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "todo"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "todo"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "todo"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "todo"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "todo"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "todo"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "todo"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "todo"} + + // TODO: + + + // FIXME: + + + // TODO(note) + + + // FIXME(note) + + + /* FIXME: */ + + + /* TODO: */ + + + /** FIXME: */ + + + /** TODO: */ diff --git a/docs/tests/trailing_closure.swift b/docs/tests/trailing_closure.swift new file mode 100644 index 0000000..e1a5821 --- /dev/null +++ b/docs/tests/trailing_closure.swift @@ -0,0 +1,22 @@ +//#Patterns: trailing_closure + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "trailing_closure"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "trailing_closure"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "trailing_closure"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "trailing_closure"} + + + +foo.map({ $0 + 1 }) + + + +foo.reduce(0, combine: { $0 + 1 }) + + + +offsets.sorted(by: { $0.offset < $1.offset }) + + + +foo.something(0, { $0 + 1 }) diff --git a/docs/tests/trailing_comma.swift b/docs/tests/trailing_comma.swift new file mode 100644 index 0000000..86baf82 --- /dev/null +++ b/docs/tests/trailing_comma.swift @@ -0,0 +1,37 @@ +//#Patterns: trailing_comma + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "trailing_comma"} +//#Issue: {"severity": "Warning", "line": 15, "patternId": "trailing_comma"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "trailing_comma"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "trailing_comma"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "trailing_comma"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "trailing_comma"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "trailing_comma"} +//#Issue: {"severity": "Warning", "line": 37, "patternId": "trailing_comma"} + + let foo = [1, 2, 3,] + + + let foo = [1, 2, 3, ] + + + let foo = [1, 2, 3 ,] + + + let foo = [1: 2, 2: 3, ] + + + struct Bar { + let foo = [1: 2, 2: 3, ] + } + + + let foo = [1, 2, 3,] + [4, 5, 6↓,] + + + let example = [ 1, + 2, + // 3, + ] + + let foo = ["אבג", "αβγ", "🇺🇸",] diff --git a/docs/tests/trailing_semicolon.swift b/docs/tests/trailing_semicolon.swift new file mode 100644 index 0000000..0d562f9 --- /dev/null +++ b/docs/tests/trailing_semicolon.swift @@ -0,0 +1,22 @@ +//#Patterns: trailing_semicolon + +//#Issue: {"severity": "Warning", "line": 9, "patternId": "trailing_semicolon"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "trailing_semicolon"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "trailing_semicolon"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "trailing_semicolon"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "trailing_semicolon"} + + let a = 0; + + + let a = 0; + let b = 1 + + + let a = 0;; + + + let a = 0; ;; + + + let a = 0; ; ; diff --git a/docs/tests/type_name.swift b/docs/tests/type_name.swift new file mode 100644 index 0000000..4db3780 --- /dev/null +++ b/docs/tests/type_name.swift @@ -0,0 +1,74 @@ +//#Patterns: type_name + +//#Issue: {"severity": "Warning", "line": 26, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 28, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 36, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 40, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 42, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 46, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 48, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 50, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 52, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 56, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 58, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 60, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 62, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 65, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 69, "patternId": "type_name"} +//#Issue: {"severity": "Warning", "line": 73, "patternId": "type_name"} + + class myType {} + + class _MyType {} + + private class MyType_ {} + + class My {} + + class AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} + + struct myType {} + + struct _MyType {} + + private struct MyType_ {} + + struct My {} + + struct AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} + + enum myType {} + + enum _MyType {} + + private enum MyType_ {} + + enum My {} + + enum AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} + + typealias X = Void + + private typealias Foo_Bar = Void + + private typealias foo = Void + + typealias AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = Void + + protocol Foo { + associatedtype X + } + + protocol Foo { + associatedtype Foo_Bar: Equatable + } + + protocol Foo { + associatedtype AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } diff --git a/docs/tests/unneeded_parentheses_in_closure_argument.swift b/docs/tests/unneeded_parentheses_in_closure_argument.swift new file mode 100644 index 0000000..6fbc13b --- /dev/null +++ b/docs/tests/unneeded_parentheses_in_closure_argument.swift @@ -0,0 +1,25 @@ +//#Patterns: unneeded_parentheses_in_closure_argument + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "unneeded_parentheses_in_closure_argument"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "unneeded_parentheses_in_closure_argument"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "unneeded_parentheses_in_closure_argument"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "unneeded_parentheses_in_closure_argument"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "unneeded_parentheses_in_closure_argument"} + + +call(arg: { (bar) in }) + + + +call(arg: { (bar, _) in }) + + + +let foo = { (bar) -> Bool in return true } + + + +foo.map { ($0, $0) }.forEach { (x, y) in } + + +foo.bar { [weak self] (x, y) in } diff --git a/docs/tests/unused_closure_parameter.swift b/docs/tests/unused_closure_parameter.swift new file mode 100644 index 0000000..c0e0f5f --- /dev/null +++ b/docs/tests/unused_closure_parameter.swift @@ -0,0 +1,46 @@ +//#Patterns: unused_closure_parameter + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "unused_closure_parameter"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "unused_closure_parameter"} +//#Issue: {"severity": "Warning", "line": 22, "patternId": "unused_closure_parameter"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "unused_closure_parameter"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "unused_closure_parameter"} +//#Issue: {"severity": "Warning", "line": 37, "patternId": "unused_closure_parameter"} +//#Issue: {"severity": "Warning", "line": 41, "patternId": "unused_closure_parameter"} +//#Issue: {"severity": "Warning", "line": 45, "patternId": "unused_closure_parameter"} + + [1, 2].map { number in + return 3 + } + + + [1, 2].map { number in + return numberWithSuffix + } + + + [1, 2].map { number in + return 3 // number + } + + + [1, 2].map { number in + return 3 "number" + } + + + [1, 2].something { number, idx in + return number + } + + + genericsFunc { (number: TypeA, idx: TypeB) in return idx + } + + + hoge(arg: num) { num in + } + + + fooFunc { 아 in + } diff --git a/docs/tests/unused_enumerated.swift b/docs/tests/unused_enumerated.swift new file mode 100644 index 0000000..cfc281c --- /dev/null +++ b/docs/tests/unused_enumerated.swift @@ -0,0 +1,14 @@ +//#Patterns: unused_enumerated + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "unused_enumerated"} +//#Issue: {"severity": "Warning", "line": 10, "patternId": "unused_enumerated"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "unused_enumerated"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "unused_enumerated"} + +for (_, foo) in bar.enumerated() { } + +for (_, foo) in abc.bar.enumerated() { } + +for (_, foo) in abc.something().enumerated() { } + +for (idx, _) in bar.enumerated() { } diff --git a/docs/tests/valid_ibinspectable.swift b/docs/tests/valid_ibinspectable.swift new file mode 100644 index 0000000..e7cc66b --- /dev/null +++ b/docs/tests/valid_ibinspectable.swift @@ -0,0 +1,55 @@ +//#Patterns: valid_ibinspectable + +//#Issue: {"severity": "Warning", "line": 14, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 19, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 34, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 39, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 44, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 49, "patternId": "valid_ibinspectable"} +//#Issue: {"severity": "Warning", "line": 54, "patternId": "valid_ibinspectable"} + + class Foo { + @IBInspectable private let count: Int + } + + + class Foo { + @IBInspectable private var insets: UIEdgeInsets + } + + + class Foo { + @IBInspectable private var count = 0 + } + + + class Foo { + @IBInspectable private var count: Int? + } + + + class Foo { + @IBInspectable private var count: Int! + } + + + class Foo { + @IBInspectable private var x: ImplicitlyUnwrappedOptional + } + + + class Foo { + @IBInspectable private var count: Optional + } + + + class Foo { + @IBInspectable private var x: Optional + } + + + class Foo { + @IBInspectable private var x: ImplicitlyUnwrappedOptional + } diff --git a/docs/tests/vertical_parameter_alignment.swift b/docs/tests/vertical_parameter_alignment.swift new file mode 100644 index 0000000..b22fa42 --- /dev/null +++ b/docs/tests/vertical_parameter_alignment.swift @@ -0,0 +1,26 @@ +//#Patterns: vertical_parameter_alignment + +//#Issue: {"severity": "Warning", "line": 11, "patternId": "vertical_parameter_alignment"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "vertical_parameter_alignment"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "vertical_parameter_alignment"} +//#Issue: {"severity": "Warning", "line": 18, "patternId": "vertical_parameter_alignment"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "vertical_parameter_alignment"} +//#Issue: {"severity": "Warning", "line": 25, "patternId": "vertical_parameter_alignment"} + +func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary) { } + +func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary) { } + +func validateFunction(_ file: SwiftLintFile, + kind: SwiftDeclarationKind, + dictionary: SourceKittenDictionary) { } + +func foo(data: Data, + @ViewBuilder content: @escaping (Data.Element.IdentifiedValue) -> Content) {} + +class A { + init(data: Data, + @ViewBuilder content: @escaping (Data.Element.IdentifiedValue) -> Content) {} +} diff --git a/docs/tests/vertical_parameter_alignment_on_call.swift b/docs/tests/vertical_parameter_alignment_on_call.swift new file mode 100644 index 0000000..979559a --- /dev/null +++ b/docs/tests/vertical_parameter_alignment_on_call.swift @@ -0,0 +1,38 @@ +//#Patterns: vertical_parameter_alignment_on_call + +//#Issue: {"severity": "Warning", "line": 14, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 21, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 32, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 35, "patternId": "vertical_parameter_alignment_on_call"} +//#Issue: {"severity": "Warning", "line": 38, "patternId": "vertical_parameter_alignment_on_call"} + +foo(param1: 1, param2: bar, + param3: false, param4: true) + +foo(param1: 1, param2: bar, + param3: false, param4: true) + +foo(param1: 1, param2: bar, + param3: false, + param4: true) + +foo(param1: 1, + param2: { _ in }) + +foo(param1: 1, + param2: { _ in +}, param3: 2, + param4: 0) + +foo(param1: 1, param2: { _ in }, + param3: false, param4: true) + +myFunc(foo: 0, + bar: baz == 0) + +myFunc(foo: 0, bar: + baz == 0, baz: true) diff --git a/docs/tests/vertical_whitespace.swift b/docs/tests/vertical_whitespace.swift new file mode 100644 index 0000000..30c2d71 --- /dev/null +++ b/docs/tests/vertical_whitespace.swift @@ -0,0 +1,17 @@ +//#Patterns: vertical_whitespace + +//#Issue: {"severity": "Warning", "line": 10, "patternId": "vertical_whitespace"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "vertical_whitespace"} + + let aaaa = 0 + + + + + struct AAAA {} + + + + + + class BBBB {} diff --git a/docs/tests/void_return.swift b/docs/tests/void_return.swift new file mode 100644 index 0000000..e0a4ac7 --- /dev/null +++ b/docs/tests/void_return.swift @@ -0,0 +1,32 @@ +//#Patterns: void_return + +//#Issue: {"severity": "Warning", "line": 11, "patternId": "void_return"} +//#Issue: {"severity": "Warning", "line": 14, "patternId": "void_return"} +//#Issue: {"severity": "Warning", "line": 17, "patternId": "void_return"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "void_return"} +//#Issue: {"severity": "Warning", "line": 23, "patternId": "void_return"} +//#Issue: {"severity": "Warning", "line": 26, "patternId": "void_return"} +//#Issue: {"severity": "Warning", "line": 29, "patternId": "void_return"} + + let abc: () -> () = {} + + + let abc: () -> (Void) = {} + + + let abc: () -> ( Void ) = {} + + + func foo(completion: () -> ()) + + + func foo(completion: () -> ( )) + + + func foo(completion: () -> (Void)) + + + let foo: (ConfigurationTests) -> () throws -> ()) + + +asd diff --git a/src/main/resources/docs/tests/weak_delegate.swift b/docs/tests/weak_delegate.swift similarity index 50% rename from src/main/resources/docs/tests/weak_delegate.swift rename to docs/tests/weak_delegate.swift index a35ec81..e815b99 100644 --- a/src/main/resources/docs/tests/weak_delegate.swift +++ b/docs/tests/weak_delegate.swift @@ -1,7 +1,7 @@ //#Patterns: weak_delegate -//#Issue: {"severity": "Info", "line": 7, "patternId": "weak_delegate"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "weak_delegate"} +//#Issue: {"severity": "Warning", "line": 7, "patternId": "weak_delegate"} +//#Issue: {"severity": "Warning", "line": 12, "patternId": "weak_delegate"} class Foo { var delegate: SomeProtocol? diff --git a/docs/tests/xctfail_message.swift b/docs/tests/xctfail_message.swift new file mode 100644 index 0000000..7ab9607 --- /dev/null +++ b/docs/tests/xctfail_message.swift @@ -0,0 +1,14 @@ +//#Patterns: xctfail_message + +//#Issue: {"severity": "Warning", "line": 8, "patternId": "xctfail_message"} +//#Issue: {"severity": "Warning", "line": 13, "patternId": "xctfail_message"} + + +func testFoo() { + XCTFail() +} + + +func testFoo() { + XCTFail("") +} diff --git a/docs/tests/yoda_condition.swift b/docs/tests/yoda_condition.swift new file mode 100644 index 0000000..55c302b --- /dev/null +++ b/docs/tests/yoda_condition.swift @@ -0,0 +1,33 @@ +//#Patterns: yoda_condition + +//#Issue: {"severity": "Warning", "line": 12, "patternId": "yoda_condition"} +//#Issue: {"severity": "Warning", "line": 16, "patternId": "yoda_condition"} +//#Issue: {"severity": "Warning", "line": 20, "patternId": "yoda_condition"} +//#Issue: {"severity": "Warning", "line": 24, "patternId": "yoda_condition"} +//#Issue: {"severity": "Warning", "line": 27, "patternId": "yoda_condition"} +//#Issue: {"severity": "Warning", "line": 30, "patternId": "yoda_condition"} +//#Issue: {"severity": "Warning", "line": 33, "patternId": "yoda_condition"} + + +if 42 == foo {} + + + +if 42.42 >= foo {} + + + +guard 42 <= foo else { return } + + + +guard "str str" != foo else { return } + + +while 10 > foo { } + + +while 1 < foo { } + + +if nil == foo diff --git a/docs/tool-description.md b/docs/tool-description.md new file mode 100644 index 0000000..513e4cf --- /dev/null +++ b/docs/tool-description.md @@ -0,0 +1 @@ +SwiftLint enforces Swift style and conventions, loosely based on GitHub's Swift Style Guide. [Learn more](https://github.com/realm/SwiftLint) \ No newline at end of file diff --git a/project/build.properties b/project/build.properties index 406a7d2..ee4c672 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.16 \ No newline at end of file +sbt.version=1.10.1 diff --git a/project/plugins.sbt b/project/plugins.sbt index 02581ab..2aebbc7 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1,3 @@ -addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.0.3") \ No newline at end of file +addSbtPlugin("com.codacy" % "codacy-sbt-plugin" % "24.0.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.8.1") +addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.1") diff --git a/src/main/resources/docs/description/description.json b/src/main/resources/docs/description/description.json deleted file mode 100755 index dd412f5..0000000 --- a/src/main/resources/docs/description/description.json +++ /dev/null @@ -1,530 +0,0 @@ -[ - { - "patternId": "attributes", - "title": "Attributes", - "timeToFix": 5, - "description": "Attributes should be on their own lines in functions and types, but on the same line as variables and imports." - }, - { - "patternId": "class_delegate_protocol", - "title": "Class Delegate Protocol", - "timeToFix": 5, - "description": "Delegate protocols should be class-only so they can be weakly referenced." - }, - { - "patternId": "closing_brace", - "title": "Closing Brace Spacing", - "timeToFix": 5, - "description": "Closing brace with closing parenthesis should not have any whitespaces in the middle." - }, - { - "patternId": "closure_end_indentation", - "title": "Closure End Indentation", - "timeToFix": 5, - "description": "Closure end should have the same indentation as the line that started it." - }, - { - "patternId": "closure_parameter_position", - "title": "Closure Parameter Position", - "timeToFix": 5, - "description": "Closure parameters should be on the same line as opening brace." - }, - { - "patternId": "closure_spacing", - "title": "Closure Spacing", - "timeToFix": 5, - "description": "Closure expressions should have a single space inside each brace." - }, - { - "patternId": "colon", - "title": "Colon", - "timeToFix": 5, - "description": "Colons should be next to the identifier when specifying a type and next to the key in dictionary literals." - }, - { - "patternId": "comma", - "title": "Comma Spacing", - "timeToFix": 5, - "description": "There should be no space before and one after any comma." - }, - { - "patternId": "compiler_protocol_init", - "title": "Compiler Protocol Init", - "timeToFix": 5, - "description": "The initializers declared in compiler protocols such as ExpressibleByArrayLiteral shouldn't be called directly." - }, - { - "patternId": "conditional_returns_on_newline", - "title": "Conditional Returns on Newline", - "timeToFix": 5, - "description": "Conditional statements should always return on the next line" - }, - { - "patternId": "control_statement", - "title": "Control Statement", - "timeToFix": 5, - "description": "if,for,while,do statements shouldn't wrap their conditionals in parentheses." - }, - { - "patternId": "custom_rules", - "title": "Custom Rules", - "timeToFix": 5, - "description": "Create custom rules by providing a regex string. Optionally specify what syntax kinds to match against, the severity level, and what message to display." - }, - { - "patternId": "cyclomatic_complexity", - "title": "Cyclomatic Complexity", - "timeToFix": 5, - "description": "Complexity of function bodies should be limited." - }, - { - "patternId": "discarded_notification_center_observer", - "title": "Discarded Notification Center Observer", - "timeToFix": 5, - "description": "When registering for a notification using a block, the opaque observer that is returned should be stored so it can be removed later." - }, - { - "patternId": "dynamic_inline", - "title": "Dynamic Inline", - "timeToFix": 5, - "description": "avoid using 'dynamic' and '@inline(__always)' together." - }, - { - "patternId": "empty_count", - "title": "Empty Count", - "timeToFix": 5, - "description": "Prefer checking isEmpty over comparing count to zero." - }, - { - "patternId": "empty_enum_arguments", - "title": "Empty Enum Arguments", - "timeToFix": 5, - "description": "Arguments can be omitted when matching enums with associated types if they are not used." - }, - { - "patternId": "empty_parameters", - "title": "Empty Parameters", - "timeToFix": 5, - "description": "Prefer () -> over Void -> ." - }, - { - "patternId": "empty_parentheses_with_trailing_closure", - "title": "Empty Parentheses with Trailing Closure", - "timeToFix": 5, - "description": "When using trailing closures, empty parentheses should be avoided after the method call." - }, - { - "patternId": "explicit_init", - "title": "Explicit Init", - "timeToFix": 5, - "description": "Explicitly calling .init() should be avoided." - }, - { - "patternId": "explicit_top_level_acl", - "title": "Explicit Top Level ACL", - "timeToFix": 5, - "description": "Top-level declarations should specify Access Control Level keywords explicitly." - }, - { - "patternId": "explicit_type_interface", - "title": "Explicit Type Interface", - "timeToFix": 5, - "description": "Properties should have a type interface" - }, - { - "patternId": "extension_access_modifier", - "title": "Extension Access Modifier", - "timeToFix": 5, - "description": "Prefer to use extension access modifiers" - }, - { - "patternId": "fatal_error_message", - "title": "Fatal Error Message", - "timeToFix": 5, - "description": "A fatalError call should have a message." - }, - { - "patternId": "file_header", - "title": "File Header", - "timeToFix": 5, - "description": "Files should have consistent header comments." - }, - { - "patternId": "file_length", - "title": "File Line Length", - "timeToFix": 5, - "description": "Files should not span too many lines." - }, - { - "patternId": "first_where", - "title": "First Where", - "timeToFix": 5, - "description": "Prefer using .first(where:) over .filter { }.first in collections." - }, - { - "patternId": "for_where", - "title": "For Where", - "timeToFix": 5, - "description": "where clauses are preferred over a single if inside a for." - }, - { - "patternId": "force_cast", - "title": "Force Cast", - "timeToFix": 5, - "description": "Force casts should be avoided." - }, - { - "patternId": "force_try", - "title": "Force Try", - "timeToFix": 5, - "description": "Force tries should be avoided." - }, - { - "patternId": "force_unwrapping", - "title": "Force Unwrapping", - "timeToFix": 5, - "description": "Force unwrapping should be avoided." - }, - { - "patternId": "function_body_length", - "title": "Function Body Length", - "timeToFix": 5, - "description": "Functions bodies should not span too many lines." - }, - { - "patternId": "function_parameter_count", - "title": "Function Parameter Count", - "timeToFix": 5, - "description": "Number of function parameters should be low." - }, - { - "patternId": "generic_type_name", - "title": "Generic Type Name", - "timeToFix": 5, - "description": "Generic type name should only contain alphanumeric characters, start with an uppercase character and span between 1 and 20 characters in length." - }, - { - "patternId": "identifier_name", - "title": "Identifier Name", - "timeToFix": 5, - "description": "Identifier names should only contain alphanumeric characters and start with a lowercase character or should only contain capital letters. In an exception to the above, variable names may start with a capital letter when they are declared static and immutable. Variable names should not be too long or too short." - }, - { - "patternId": "implicit_getter", - "title": "Implicit Getter", - "timeToFix": 5, - "description": "Computed read-only properties should avoid using the get keyword." - }, - { - "patternId": "implicit_return", - "title": "Implicit Return", - "timeToFix": 5, - "description": "Prefer implicit returns in closures." - }, - { - "patternId": "implicitly_unwrapped_optional", - "title": "Implicitly Unwrapped Optional", - "timeToFix": 5, - "description": "Implicitly unwrapped optionals should be avoided when possible." - }, - { - "patternId": "large_tuple", - "title": "Large Tuple", - "timeToFix": 5, - "description": "Tuples shouldn't have too many members. Create a custom type instead." - }, - { - "patternId": "leading_whitespace", - "title": "Leading Whitespace", - "timeToFix": 5, - "description": "Files should not contain leading whitespace." - }, - { - "patternId": "legacy_cggeometry_functions", - "title": "Legacy CGGeometry Functions", - "timeToFix": 5, - "description": "Struct extension properties and methods are preferred over legacy functions" - }, - { - "patternId": "legacy_constant", - "title": "Legacy Constant", - "timeToFix": 5, - "description": "Struct-scoped constants are preferred over legacy global constants." - }, - { - "patternId": "legacy_constructor", - "title": "Legacy Constructor", - "timeToFix": 5, - "description": "Swift constructors are preferred over legacy convenience functions." - }, - { - "patternId": "legacy_nsgeometry_functions", - "title": "Legacy NSGeometry Functions", - "timeToFix": 5, - "description": "Struct extension properties and methods are preferred over legacy functions" - }, - { - "patternId": "line_length", - "title": "Line Length", - "timeToFix": 5, - "description": "Lines should not span too many characters." - }, - { - "patternId": "mark", - "title": "Mark", - "timeToFix": 5, - "description": "MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'" - }, - { - "patternId": "multiline_parameters", - "title": "Multiline Parameters", - "timeToFix": 5, - "description": "Functions and methods parameters should be either on the same line, or one per line." - }, - { - "patternId": "nesting", - "title": "Nesting", - "timeToFix": 5, - "description": "Types should be nested at most 1 level deep, and statements should be nested at most 5 levels deep." - }, - { - "patternId": "nimble_operator", - "title": "Nimble Operator", - "timeToFix": 5, - "description": "Prefer Nimble operator overloads over free matcher functions." - }, - { - "patternId": "no_extension_access_modifier", - "title": "No Extension Access Modifier", - "timeToFix": 5, - "description": "Prefer not to use extension access modifiers" - }, - { - "patternId": "notification_center_detachment", - "title": "Notification Center Detachment", - "timeToFix": 5, - "description": "An object should only remove itself as an observer in deinit." - }, - { - "patternId": "number_separator", - "title": "Number Separator", - "timeToFix": 5, - "description": "Underscores should be used as thousand separator in large decimal numbers." - }, - { - "patternId": "object_literal", - "title": "Object Literal", - "timeToFix": 5, - "description": "Prefer object literals over image and color inits." - }, - { - "patternId": "opening_brace", - "title": "Opening Brace Spacing", - "timeToFix": 5, - "description": "Opening braces should be preceded by a single space and on the same line as the declaration." - }, - { - "patternId": "operator_usage_whitespace", - "title": "Operator Usage Whitespace", - "timeToFix": 5, - "description": "Operators should be surrounded by a single whitespace when they are being used." - }, - { - "patternId": "operator_whitespace", - "title": "Operator Function Whitespace", - "timeToFix": 5, - "description": "Operators should be surrounded by a single whitespace when defining them." - }, - { - "patternId": "overridden_super_call", - "title": "Overridden methods call super", - "timeToFix": 5, - "description": "Some overridden methods should always call super" - }, - { - "patternId": "private_outlet", - "title": "Private Outlets", - "timeToFix": 5, - "description": "IBOutlets should be private to avoid leaking UIKit to higher layers." - }, - { - "patternId": "private_unit_test", - "title": "Private Unit Test", - "timeToFix": 5, - "description": "Unit tests marked private are silently skipped." - }, - { - "patternId": "prohibited_super_call", - "title": "Prohibited calls to super", - "timeToFix": 5, - "description": "Some methods should not call super" - }, - { - "patternId": "protocol_property_accessors_order", - "title": "Protocol Property Accessors Order", - "timeToFix": 5, - "description": "When declaring properties in protocols, the order of accessors should be get set." - }, - { - "patternId": "redundant_discardable_let", - "title": "Redundant Discardable Let", - "timeToFix": 5, - "description": "Prefer _ = foo() over let _ = foo() when discarding a result from a function." - }, - { - "patternId": "redundant_nil_coalescing", - "title": "Redundant Nil Coalescing", - "timeToFix": 5, - "description": "nil coalescing operator is only evaluated if the lhs is nil, coalescing operator with nil as rhs is redundant" - }, - { - "patternId": "redundant_optional_initialization", - "title": "Redundant Optional Initialization", - "timeToFix": 5, - "description": "Initializing an optional variable with nil is redundant." - }, - { - "patternId": "redundant_string_enum_value", - "title": "Redundant String Enum Value", - "timeToFix": 5, - "description": "String enum values can be omitted when they are equal to the enumcase name." - }, - { - "patternId": "redundant_void_return", - "title": "Redundant Void Return", - "timeToFix": 5, - "description": "Returning Void in a function declaration is redundant." - }, - { - "patternId": "return_arrow_whitespace", - "title": "Returning Whitespace", - "timeToFix": 5, - "description": "Return arrow and return type should be separated by a single space or on a separate line." - }, - { - "patternId": "shorthand_operator", - "title": "Shorthand Operator", - "timeToFix": 5, - "description": "Prefer shorthand operators (+=, -=, *=, /=) over doing the operation and assigning." - }, - { - "patternId": "sorted_imports", - "title": "Sorted Imports", - "timeToFix": 5, - "description": "Imports should be sorted." - }, - { - "patternId": "statement_position", - "title": "Statement Position", - "timeToFix": 5, - "description": "Else and catch should be on the same line, one space after the previous declaration." - }, - { - "patternId": "switch_case_on_newline", - "title": "Switch Case on Newline", - "timeToFix": 5, - "description": "Cases inside a switch should always be on a newline" - }, - { - "patternId": "syntactic_sugar", - "title": "Syntactic Sugar", - "timeToFix": 5, - "description": "Shorthand syntactic sugar should be used, i.e. [Int] instead of Array" - }, - { - "patternId": "todo", - "title": "Todo", - "timeToFix": 5, - "description": "TODOs and FIXMEs should be avoided." - }, - { - "patternId": "trailing_comma", - "title": "Trailing Comma", - "timeToFix": 5, - "description": "Trailing commas in arrays and dictionaries should be avoided/enforced." - }, - { - "patternId": "trailing_newline", - "title": "Trailing Newline", - "timeToFix": 5, - "description": "Files should have a single trailing newline." - }, - { - "patternId": "trailing_semicolon", - "title": "Trailing Semicolon", - "timeToFix": 5, - "description": "Lines should not have trailing semicolons." - }, - { - "patternId": "trailing_whitespace", - "title": "Trailing Whitespace", - "timeToFix": 5, - "description": "Lines should not have trailing whitespace." - }, - { - "patternId": "type_body_length", - "title": "Type Body Length", - "timeToFix": 5, - "description": "Type bodies should not span too many lines." - }, - { - "patternId": "type_name", - "title": "Type Name", - "timeToFix": 5, - "description": "Type name should only contain alphanumeric characters, start with an uppercase character and span between 3 and 40 characters in length." - }, - { - "patternId": "unused_closure_parameter", - "title": "Unused Closure Parameter", - "timeToFix": 5, - "description": "Unused parameter in a closure should be replaced with _." - }, - { - "patternId": "unused_enumerated", - "title": "Unused Enumerated", - "timeToFix": 5, - "description": "When the index or the item is not used, .enumerated() can be removed." - }, - { - "patternId": "unused_optional_binding", - "title": "Unused Optional Binding", - "timeToFix": 5, - "description": "Prefer != nil over let _ =" - }, - { - "patternId": "valid_ibinspectable", - "title": "Valid IBInspectable", - "timeToFix": 5, - "description": "@IBInspectable should be applied to variables only, have its type explicit and be of a supported type" - }, - { - "patternId": "vertical_parameter_alignment", - "title": "Vertical Parameter Alignment", - "timeToFix": 5, - "description": "Function parameters should be aligned vertically if they're in multiple lines in a declaration." - }, - { - "patternId": "vertical_parameter_alignment_on_call", - "title": "Vertical Parameter Alignment On Call", - "timeToFix": 5, - "description": "Function parameters should be aligned vertically if they're in multiple lines in a method call." - }, - { - "patternId": "vertical_whitespace", - "title": "Vertical Whitespace", - "timeToFix": 5, - "description": "Limit vertical whitespace to a single empty line." - }, - { - "patternId": "void_return", - "title": "Void Return", - "timeToFix": 5, - "description": "Prefer -> Void over -> ()." - }, - { - "patternId": "weak_delegate", - "title": "Weak Delegate", - "timeToFix": 5, - "description": "Delegates should be weak to avoid reference cycles." - } -] diff --git a/src/main/resources/docs/patterns.json b/src/main/resources/docs/patterns.json deleted file mode 100755 index 4043fc8..0000000 --- a/src/main/resources/docs/patterns.json +++ /dev/null @@ -1,445 +0,0 @@ -{ - "name": "swiftlint", - "patterns": [ - { - "patternId": "attributes", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "class_delegate_protocol", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "closing_brace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "closure_end_indentation", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "closure_parameter_position", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "closure_spacing", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "colon", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "comma", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "compiler_protocol_init", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "conditional_returns_on_newline", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "control_statement", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "custom_rules", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "cyclomatic_complexity", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "discarded_notification_center_observer", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "dynamic_inline", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "empty_count", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "empty_enum_arguments", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "empty_parameters", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "empty_parentheses_with_trailing_closure", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "explicit_init", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "explicit_top_level_acl", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "explicit_type_interface", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "extension_access_modifier", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "fatal_error_message", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "file_header", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "file_length", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "first_where", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "for_where", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "force_cast", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "force_try", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "force_unwrapping", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "function_body_length", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "function_parameter_count", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "generic_type_name", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "identifier_name", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "implicit_getter", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "implicit_return", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "implicitly_unwrapped_optional", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "large_tuple", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "leading_whitespace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "legacy_cggeometry_functions", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "legacy_constant", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "legacy_constructor", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "legacy_nsgeometry_functions", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "line_length", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "mark", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "multiline_parameters", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "nesting", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "nimble_operator", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "no_extension_access_modifier", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "notification_center_detachment", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "number_separator", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "object_literal", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "opening_brace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "operator_usage_whitespace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "operator_whitespace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "overridden_super_call", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "private_outlet", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "private_unit_test", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "prohibited_super_call", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "protocol_property_accessors_order", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "redundant_discardable_let", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "redundant_nil_coalescing", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "redundant_optional_initialization", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "redundant_string_enum_value", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "redundant_void_return", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "return_arrow_whitespace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "shorthand_operator", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "sorted_imports", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "statement_position", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "switch_case_on_newline", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "syntactic_sugar", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "todo", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "trailing_comma", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "trailing_newline", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "trailing_semicolon", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "trailing_whitespace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "type_body_length", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "type_name", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "unused_closure_parameter", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "unused_enumerated", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "unused_optional_binding", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "valid_ibinspectable", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "vertical_parameter_alignment", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "vertical_parameter_alignment_on_call", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "vertical_whitespace", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "void_return", - "level": "Info", - "category": "CodeStyle" - }, - { - "patternId": "weak_delegate", - "level": "Info", - "category": "CodeStyle" - } - ] -} diff --git a/src/main/resources/docs/tests/attributes.swift b/src/main/resources/docs/tests/attributes.swift deleted file mode 100644 index 4891581..0000000 --- a/src/main/resources/docs/tests/attributes.swift +++ /dev/null @@ -1,131 +0,0 @@ -//#Patterns: attributes - -//#Issue: {"severity": "Info", "line": 37, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 41, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 57, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 60, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 63, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 65, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 68, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 71, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 75, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 77, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 79, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 81, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 84, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 87, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 91, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 93, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 95, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 98, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 103, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 105, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 108, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 111, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 115, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 118, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 121, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 123, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 126, "patternId": "attributes"} -//#Issue: {"severity": "Info", "line": 131, "patternId": "attributes"} - - @objc - var x: String - - @objc - - var x: String - - @objc - private var x: String - - @nonobjc - var x: String - - @IBOutlet - private var label: UILabel - - @IBOutlet - - private var label: UILabel - - @NSCopying - var name: NSString - - @NSManaged - var name: String? - - @IBInspectable - var cornerRadius: CGFloat - - @available(iOS 9.0, *) let stackView: UIStackView - - @NSManaged - func addSomeObject(book: SomeObject) - - @IBAction - func buttonPressed(button: UIButton) - - @IBAction - @objc - func buttonPressed(button: UIButton) - - @available(iOS 9.0, *) func animate(view: UIStackView) - - @nonobjc final class X - - @available(iOS 9.0, *) class UIStackView - - @available(iOS 9.0, *) - @objc class UIStackView - - @available(iOS 9.0, *) @objc - class UIStackView - - @available(iOS 9.0, *) - - class UIStackView - - @UIApplicationMain class AppDelegate: NSObject, UIApplicationDelegate - - @IBDesignable class MyCustomView: UIView - - @testable - import SourceKittenFramework - - @testable - - - import SourceKittenFramework - - @objc(foo_x) var x: String - - @available(iOS 9.0, *) @objc(abc_stackView) - let stackView: UIStackView - - @objc(abc_addSomeObject:) @NSManaged - func addSomeObject(book: SomeObject) - - @objc(abc_addSomeObject:) - @NSManaged - func addSomeObject(book: SomeObject) - - @available(iOS 9.0, *) - @objc(ABCThing) class Thing - - @GKInspectable - var maxSpeed: Float - - @discardableResult func a() -> Int - - @objc - @discardableResult func a() -> Int - - @objc - - @discardableResult - func a() -> Int diff --git a/src/main/resources/docs/tests/class_delegate_protocol.swift b/src/main/resources/docs/tests/class_delegate_protocol.swift deleted file mode 100644 index aa0957c..0000000 --- a/src/main/resources/docs/tests/class_delegate_protocol.swift +++ /dev/null @@ -1,10 +0,0 @@ -//#Patterns: class_delegate_protocol - -//#Issue: {"severity": "Info", "line": 6, "patternId": "class_delegate_protocol"} -//#Issue: {"severity": "Info", "line": 9, "patternId": "class_delegate_protocol"} - - protocol FooDelegate {} - - - protocol FooDelegate: Bar {} - diff --git a/src/main/resources/docs/tests/closing_brace.swift b/src/main/resources/docs/tests/closing_brace.swift deleted file mode 100644 index 78c9abe..0000000 --- a/src/main/resources/docs/tests/closing_brace.swift +++ /dev/null @@ -1,9 +0,0 @@ -//#Patterns: closing_brace - -//#Issue: {"severity": "Info", "line": 6, "patternId": "closing_brace"} -//#Issue: {"severity": "Info", "line": 8, "patternId": "closing_brace"} - - [].map({ } ) - - [].map({ } ) - diff --git a/src/main/resources/docs/tests/closure_parameter_position.swift b/src/main/resources/docs/tests/closure_parameter_position.swift deleted file mode 100644 index 6e91100..0000000 --- a/src/main/resources/docs/tests/closure_parameter_position.swift +++ /dev/null @@ -1,56 +0,0 @@ -//#Patterns: closure_parameter_position - -//#Issue: {"severity": "Info", "line": 12, "patternId": "closure_parameter_position"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "closure_parameter_position"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "closure_parameter_position"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "closure_parameter_position"} -//#Issue: {"severity": "Info", "line": 36, "patternId": "closure_parameter_position"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "closure_parameter_position"} -//#Issue: {"severity": "Info", "line": 48, "patternId": "closure_parameter_position"} - - [1, 2].map { - number in - number + 1 - } - - - [1, 2].map { - number -> Int in - number + 1 - } - - - [1, 2].map { - (number: Int) -> Int in - number + 1 - } - - - [1, 2].map { - [weak self] number in - number + 1 - } - - - [1, 2].map { [weak self] - number in - number + 1 - } - - - [1, 2].map({ - number in - number + 1 - }) - - - [1, 2].something(closure: { - number in - number + 1 - }) - - - [1, 2].reduce(0) { - sum, ↓number in - number + sum - } diff --git a/src/main/resources/docs/tests/closure_spacing.swift b/src/main/resources/docs/tests/closure_spacing.swift deleted file mode 100644 index d0059c6..0000000 --- a/src/main/resources/docs/tests/closure_spacing.swift +++ /dev/null @@ -1,16 +0,0 @@ -//#Patterns: closure_spacing - -//#Issue: {"severity": "Info", "line": 10, "patternId": "closure_spacing"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "closure_spacing"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "closure_spacing"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "closure_spacing"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "closure_spacing"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "closure_spacing"} - - [].filter({$0.contains(location)}) - - [].map({$0}) - - ({each in return result.contains(where: ↓{e in return e}) }).count - - filter { sorted ↓{ $0 < $1}} diff --git a/src/main/resources/docs/tests/colon.swift b/src/main/resources/docs/tests/colon.swift deleted file mode 100644 index 412c5a0..0000000 --- a/src/main/resources/docs/tests/colon.swift +++ /dev/null @@ -1,178 +0,0 @@ -//#Patterns: colon - -//#Issue: {"severity": "Info", "line": 49, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 52, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 55, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 58, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 61, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 64, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 67, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 70, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 73, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 76, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 79, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 82, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 85, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 88, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 91, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 94, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 97, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 100, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 103, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 106, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 109, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 112, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 115, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 118, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 121, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 124, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 127, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 130, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 130, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 133, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 136, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 139, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 142, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 145, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 148, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 151, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 154, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 157, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 160, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 163, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 166, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 169, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 172, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 175, "patternId": "colon"} -//#Issue: {"severity": "Info", "line": 178, "patternId": "colon"} - - let abc:Void - - - let abc: Void - - - let abc :Void - - - let abc : Void - - - let abc : [Void: Void] - - - let abc : (Void, String, Int) - - - let abc : ([Void], String, Int) - - - let abc : [([Void], String, Int)] - - - let abc: (Void, String, Int) - - - let abc: ([Void], String, Int) - - - let abc: [([Void], String, Int)] - - - let abc :String="def" - - - let abc :Int=0 - - - let abc :Int = 0 - - - let abc:Int=0 - - - let abc:Int = 0 - - - let abc:Enum=Enum.Value - - - func abc(def:Void) {} - - - func abc(def: Void) {} - - - func abc(def :Void) {} - - - func abc(def : Void) {} - - - func abc(def: Void, ghi :Void) {} - - - let abc = [Void:Void]() - - - let abc = [Void : Void]() - - - let abc = [Void: Void]() - - - let abc = [Void : Void]() - - - let abc = [1: [3 : 2], 3: 4] - - - let abc = [1: [3 : 2], 3↓: 4] - - - let abc: [String : Int] - - - let abc: [String:Int] - - - func foo(bar: [String : Int]) {} - - - func foo(bar: [String:Int]) {} - - - func foo() -> [String : Int] { return [:] } - - - func foo() -> [String:Int] { return [:] } - - - let abc : Any - - - let abc: [Any : Int] - - - let abc: [String : Any] - - - class Foo : Bar {} - - - class Foo:Bar {} - - - class Foo {} - - - class Foo {} - - - object.method(x: 5, y : "string") - - - object.method(x:5, y: "string") - - - object.method(x: 5, y: "string") diff --git a/src/main/resources/docs/tests/comma.swift b/src/main/resources/docs/tests/comma.swift deleted file mode 100644 index dd013c2..0000000 --- a/src/main/resources/docs/tests/comma.swift +++ /dev/null @@ -1,22 +0,0 @@ -//#Patterns: comma - -//#Issue: {"severity": "Info", "line": 11, "patternId": "comma"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "comma"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "comma"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "comma"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "comma"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "comma"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "comma"} - - func abc(a: String ,b: String) { } - - func abc(a: String ,b: String↓ ,c: String↓ ,d: String) { } - - abc(a: "string",b: "string" - - enum a { case a ,b } - - let result = plus( - first: 3 , // #683 - second: 4 - ) diff --git a/src/main/resources/docs/tests/compiler_protocol_init.swift b/src/main/resources/docs/tests/compiler_protocol_init.swift deleted file mode 100644 index 0acb9a1..0000000 --- a/src/main/resources/docs/tests/compiler_protocol_init.swift +++ /dev/null @@ -1,9 +0,0 @@ -//#Patterns: compiler_protocol_init - -//#Issue: {"severity": "Info", "line": 6, "patternId": "compiler_protocol_init"} -//#Issue: {"severity": "Info", "line": 9, "patternId": "compiler_protocol_init"} - - let set = Set(arrayLiteral: 1, 2) - - - let set = Set.init(arrayLiteral: 1, 2) diff --git a/src/main/resources/docs/tests/conditional_returns_on_newline.swift b/src/main/resources/docs/tests/conditional_returns_on_newline.swift deleted file mode 100644 index bd91447..0000000 --- a/src/main/resources/docs/tests/conditional_returns_on_newline.swift +++ /dev/null @@ -1,17 +0,0 @@ -//#Patterns: conditional_returns_on_newline - -//#Issue: {"severity": "Info", "line": 9, "patternId": "conditional_returns_on_newline"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "conditional_returns_on_newline"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "conditional_returns_on_newline"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "conditional_returns_on_newline"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "conditional_returns_on_newline"} - - guard true else { return } - - if true { return } - - if true { break } else { return } - - if true { break } else { return } - - if true { return "YES" } else { return "NO" } diff --git a/src/main/resources/docs/tests/control_statement.swift b/src/main/resources/docs/tests/control_statement.swift deleted file mode 100644 index 7e04643..0000000 --- a/src/main/resources/docs/tests/control_statement.swift +++ /dev/null @@ -1,65 +0,0 @@ -//#Patterns: control_statement - -//#Issue: {"severity": "Info", "line": 20, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 41, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 53, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 59, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 62, "patternId": "control_statement"} -//#Issue: {"severity": "Info", "line": 65, "patternId": "control_statement"} - - if (condition) { - - - if(condition) { - - - if ((a || b) && (c || d)) { - - - if ((min...max).contains(value)) { - - - for (item in collection) { - - - for (var index = 0; index < 42; index++) { - - - for(item in collection) { - - - for(var index = 0; index < 42; index++) { - - - guard (condition) else { - - - while (condition) { - - - while(condition) { - - - } while (condition) { - - - } while(condition) { - - - do { ; } while(condition) { - - - do { ; } while (condition) { - - - switch (foo) { diff --git a/src/main/resources/docs/tests/dynamic_inline.swift b/src/main/resources/docs/tests/dynamic_inline.swift deleted file mode 100644 index a173305..0000000 --- a/src/main/resources/docs/tests/dynamic_inline.swift +++ /dev/null @@ -1,30 +0,0 @@ -//#Patterns: dynamic_inline - -//#Issue: {"severity": "Info", "line": 10, "patternId": "dynamic_inline"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "dynamic_inline"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "dynamic_inline"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "dynamic_inline"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "dynamic_inline"} - - class C { - @inline(__always) dynamic func f() {} - } - - class C { - @inline(__always) public dynamic func f() {} - } - - class C { - @inline(__always) dynamic internal func f() {} - } - - class C { - @inline(__always) - dynamic func f() {} - } - - class C { - @inline(__always) - dynamic - func f() {} - } diff --git a/src/main/resources/docs/tests/empty_count.swift b/src/main/resources/docs/tests/empty_count.swift deleted file mode 100644 index dd32943..0000000 --- a/src/main/resources/docs/tests/empty_count.swift +++ /dev/null @@ -1,18 +0,0 @@ -//#Patterns: empty_count - -//#Issue: {"severity": "Info", "line": 8, "patternId": "empty_count"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "empty_count"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "empty_count"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "empty_count"} - - [Int]().count == 0 - - - [Int]().count > 0 - - - [Int]().count != 0 - - - count == 0 - diff --git a/src/main/resources/docs/tests/empty_enum_arguments.swift b/src/main/resources/docs/tests/empty_enum_arguments.swift deleted file mode 100644 index 54d30b5..0000000 --- a/src/main/resources/docs/tests/empty_enum_arguments.swift +++ /dev/null @@ -1,23 +0,0 @@ -//#Patterns: empty_enum_arguments - -//#Issue: {"severity": "Info", "line": 10, "patternId": "empty_enum_arguments"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "empty_enum_arguments"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "empty_enum_arguments"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "empty_enum_arguments"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "empty_enum_arguments"} - - switch foo { - case .bar(_): break - } - - switch foo { - case .bar(): break - } - - switch foo { - case .bar(_), .bar2↓(_): break - } - - switch foo { - case .bar() where method() > 2: break - } diff --git a/src/main/resources/docs/tests/empty_parameters.swift b/src/main/resources/docs/tests/empty_parameters.swift deleted file mode 100644 index b51bec5..0000000 --- a/src/main/resources/docs/tests/empty_parameters.swift +++ /dev/null @@ -1,17 +0,0 @@ -//#Patterns: empty_parameters - -//#Issue: {"severity": "Info", "line": 8, "patternId": "empty_parameters"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "empty_parameters"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "empty_parameters"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "empty_parameters"} - - let abc: (Void) -> Void = {} - - - func foo(completion: (Void) -> Void) - - - func foo(completion: (Void) throws -> Void) - - - let foo: (Void) -> () throws -> Void) diff --git a/src/main/resources/docs/tests/empty_parentheses_with_trailing_closure.swift b/src/main/resources/docs/tests/empty_parentheses_with_trailing_closure.swift deleted file mode 100644 index 2b3c2c6..0000000 --- a/src/main/resources/docs/tests/empty_parentheses_with_trailing_closure.swift +++ /dev/null @@ -1,21 +0,0 @@ -//#Patterns: empty_parentheses_with_trailing_closure - -//#Issue: {"severity": "Info", "line": 8, "patternId": "empty_parentheses_with_trailing_closure"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "empty_parentheses_with_trailing_closure"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "empty_parentheses_with_trailing_closure"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "empty_parentheses_with_trailing_closure"} - - [1, 2].map() { $0 + 1 } - - - [1, 2].map( ) { $0 + 1 } - - - [1, 2].map() { number in - number + 1 - } - - - [1, 2].map( ) { number in - number + 1 - } diff --git a/src/main/resources/docs/tests/explicit_init.swift b/src/main/resources/docs/tests/explicit_init.swift deleted file mode 100644 index 1d1ceb5..0000000 --- a/src/main/resources/docs/tests/explicit_init.swift +++ /dev/null @@ -1,8 +0,0 @@ -//#Patterns: explicit_init - -//#Issue: {"severity": "Info", "line": 6, "patternId": "explicit_init"} -//#Issue: {"severity": "Info", "line": 8, "patternId": "explicit_init"} - - [1].flatMap{String.init($0)} - - [String.self].map { Type in Type.init(1) } diff --git a/src/main/resources/docs/tests/explicit_top_level_acl.swift b/src/main/resources/docs/tests/explicit_top_level_acl.swift deleted file mode 100644 index 203e709..0000000 --- a/src/main/resources/docs/tests/explicit_top_level_acl.swift +++ /dev/null @@ -1,22 +0,0 @@ -//#Patterns: explicit_top_level_acl - -//#Issue: {"severity": "Info", "line": 9, "patternId": "explicit_top_level_acl"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "explicit_top_level_acl"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "explicit_top_level_acl"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "explicit_top_level_acl"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "explicit_top_level_acl"} - - enum A {} - - - final class B {} - - - struct C {} - - - func a() {} - - - internal let a = 0 - func b() {} diff --git a/src/main/resources/docs/tests/explicit_type_interface.swift b/src/main/resources/docs/tests/explicit_type_interface.swift deleted file mode 100644 index be60069..0000000 --- a/src/main/resources/docs/tests/explicit_type_interface.swift +++ /dev/null @@ -1,27 +0,0 @@ -//#Patterns: explicit_type_interface - -//#Issue: {"severity": "Info", "line": 9, "patternId": "explicit_type_interface"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "explicit_type_interface"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "explicit_type_interface"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "explicit_type_interface"} - - class Foo { - var myVar = 0 - - } - - - class Foo { - let mylet = 0 - - } - - - class Foo { - static var myStaticVar = 0 - } - - - class Foo { - class var myClassVar = 0 - } diff --git a/src/main/resources/docs/tests/extension_access_modifier.swift b/src/main/resources/docs/tests/extension_access_modifier.swift deleted file mode 100644 index 1f765d5..0000000 --- a/src/main/resources/docs/tests/extension_access_modifier.swift +++ /dev/null @@ -1,21 +0,0 @@ -//#Patterns: extension_access_modifier - -//#Issue: {"severity": "Info", "line": 8, "patternId": "extension_access_modifier"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "extension_access_modifier"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "extension_access_modifier"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "extension_access_modifier"} - - extension Foo { - public var bar: Int { return 1 } - public var baz: Int { return 1 } - } - - extension Foo { - public var bar: Int { return 1 } - public func baz() {} - } - - public extension Foo { - public func bar() {} - public func baz() {} - } diff --git a/src/main/resources/docs/tests/fatal_error_message.swift b/src/main/resources/docs/tests/fatal_error_message.swift deleted file mode 100644 index 3820dec..0000000 --- a/src/main/resources/docs/tests/fatal_error_message.swift +++ /dev/null @@ -1,13 +0,0 @@ -//#Patterns: fatal_error_message - -//#Issue: {"severity": "Info", "line": 7, "patternId": "fatal_error_message"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "fatal_error_message"} - - func foo() { - fatalError("") - } - - - func foo() { - fatalError() - } diff --git a/src/main/resources/docs/tests/file_header.swift b/src/main/resources/docs/tests/file_header.swift deleted file mode 100644 index 8dac875..0000000 --- a/src/main/resources/docs/tests/file_header.swift +++ /dev/null @@ -1,17 +0,0 @@ -//#Patterns: file_header - -//#Issue: {"severity": "Info", "line": 5, "patternId": "file_header"} - - // Copyright - - - // - // Copyright - - // - // FileHeaderRule.swift - // SwiftLint - // - // Created by Marcelo Fabri on 27/11/16. - // Copyright © 2016 Realm. All rights reserved. - // diff --git a/src/main/resources/docs/tests/first_where.swift b/src/main/resources/docs/tests/first_where.swift deleted file mode 100644 index 7b948d1..0000000 --- a/src/main/resources/docs/tests/first_where.swift +++ /dev/null @@ -1,27 +0,0 @@ -//#Patterns: first_where - -//#Issue: {"severity": "Info", "line": 10, "patternId": "first_where"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "first_where"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "first_where"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "first_where"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "first_where"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "first_where"} - - myList.filter { $0 % 2 == 0 }.first - - - myList.filter({ $0 % 2 == 0 }).first - - - myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first - - - myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first?.something() - - - myList.filter(someFunction).first - - - myList.filter({ $0 % 2 == 0 }) - .first - diff --git a/src/main/resources/docs/tests/force_cast.swift b/src/main/resources/docs/tests/force_cast.swift deleted file mode 100644 index c31ff9a..0000000 --- a/src/main/resources/docs/tests/force_cast.swift +++ /dev/null @@ -1,5 +0,0 @@ -//#Patterns: force_cast - -//#Issue: {"severity": "Info", "line": 5, "patternId": "force_cast"} - - NSNumber() as! Int diff --git a/src/main/resources/docs/tests/force_try.swift b/src/main/resources/docs/tests/force_try.swift deleted file mode 100644 index 48f1357..0000000 --- a/src/main/resources/docs/tests/force_try.swift +++ /dev/null @@ -1,5 +0,0 @@ -//#Patterns: force_try - -//#Issue: {"severity": "Info", "line": 5, "patternId": "force_try"} - - func a() throws {}; try! a() diff --git a/src/main/resources/docs/tests/force_unwrapping.swift b/src/main/resources/docs/tests/force_unwrapping.swift deleted file mode 100644 index 64f9622..0000000 --- a/src/main/resources/docs/tests/force_unwrapping.swift +++ /dev/null @@ -1,43 +0,0 @@ -//#Patterns: force_unwrapping - -//#Issue: {"severity": "Info", "line": 17, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 31, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 37, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "force_unwrapping"} -//#Issue: {"severity": "Info", "line": 43, "patternId": "force_unwrapping"} - - let url = NSURL(string: query)! - - navigationController!.pushViewController(viewController, animated: true) - - let unwrapped = optional! - - return cell! - - let url = NSURL(string: "http://www.google.com")! - - let dict = ["Boooo": "👻"]func bla() -> String { return dict["Boooo"]! } - - let dict = ["Boooo": "👻"]func bla() -> String { return dict["Boooo"]!.contains("B") } - - let a = dict["abc"]!.contains("B") - - dict["abc"]!.bar("B") - - if dict["a"]!!!! { - - var foo: [Bool]! = dict["abc"]! - - context("abc") { - var foo: [Bool]! = dict["abc"]! - } - - open var computed: String { return foo.bar! } diff --git a/src/main/resources/docs/tests/generic_type_name.swift b/src/main/resources/docs/tests/generic_type_name.swift deleted file mode 100644 index a8f0acf..0000000 --- a/src/main/resources/docs/tests/generic_type_name.swift +++ /dev/null @@ -1,92 +0,0 @@ -//#Patterns: generic_type_name - -//#Issue: {"severity": "Info", "line": 29, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 41, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 53, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 59, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 62, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 65, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 68, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 71, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 71, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 74, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 77, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 80, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 83, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 86, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 86, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 89, "patternId": "generic_type_name"} -//#Issue: {"severity": "Info", "line": 92, "patternId": "generic_type_name"} - - func foo() {} - - - func foo(param: U_Foo) -> T {} - - - func foo() {} - - - func foo() {} - - - typealias StringDictionary = Dictionary - - - typealias BackwardTriple = (T3, T2_Bar, T1) - - - typealias DictionaryOfStrings = Dictionary - - - class Foo {} - - - class Foo {} - - - class Foo {} - - - class Foo {} - - - class Foo {} - - - struct Foo {} - - - struct Foo {} - - - struct Foo {} - - - struct Foo {} - - - struct Foo {} - - - enum Foo {} - - - enum Foo {} - - - enum Foo {} - - - enum Foo {} - - - enum Foo {} diff --git a/src/main/resources/docs/tests/identifier_name.swift b/src/main/resources/docs/tests/identifier_name.swift deleted file mode 100644 index ff4d478..0000000 --- a/src/main/resources/docs/tests/identifier_name.swift +++ /dev/null @@ -1,35 +0,0 @@ -//#Patterns: identifier_name - -//#Issue: {"severity": "Info", "line": 15, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 31, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "identifier_name"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "identifier_name"} - - let MyLet = 0 - - let _myLet = 0 - - private let myLet_ = 0 - - let myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0 - - var myExtremelyVeryVeryVeryVeryVeryVeryLongVar = 0 - - private let _myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0 - - let i = 0 - - var id = 0 - - private let _i = 0 - - func IsOperator(name: String) -> Bool - - enum Foo { case MyEnum } diff --git a/src/main/resources/docs/tests/implicit_getter.swift b/src/main/resources/docs/tests/implicit_getter.swift deleted file mode 100644 index 00e8c0c..0000000 --- a/src/main/resources/docs/tests/implicit_getter.swift +++ /dev/null @@ -1,55 +0,0 @@ -//#Patterns: implicit_getter - -//#Issue: {"severity": "Info", "line": 11, "patternId": "implicit_getter"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "implicit_getter"} -//#Issue: {"severity": "Info", "line": 31, "patternId": "implicit_getter"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "implicit_getter"} -//#Issue: {"severity": "Info", "line": 49, "patternId": "implicit_getter"} - - class Foo { - var foo: Int { - get { - return 20 - } - } - } - } - - - class Foo { - var foo: Int { - get{ - return 20 - } - } - } - } - - - class Foo { - static var foo: Int { - get { - return 20 - } - } - } - } - - - var foo: Int { - get { - return 20 - } - } - } - - class Foo { - @objc func bar() { } - var foo: Int { - get { - return 20 - } - } - } - } - diff --git a/src/main/resources/docs/tests/implicit_return.swift b/src/main/resources/docs/tests/implicit_return.swift deleted file mode 100644 index e0d199f..0000000 --- a/src/main/resources/docs/tests/implicit_return.swift +++ /dev/null @@ -1,12 +0,0 @@ -//#Patterns: implicit_return - -//#Issue: {"severity": "Info", "line": 7, "patternId": "implicit_return"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "implicit_return"} - - foo.map { value in - return value + 1 - } - - foo.map { - return $0 + 1 - } diff --git a/src/main/resources/docs/tests/implicitly_unwrapped_optional.swift b/src/main/resources/docs/tests/implicitly_unwrapped_optional.swift deleted file mode 100644 index 253c693..0000000 --- a/src/main/resources/docs/tests/implicitly_unwrapped_optional.swift +++ /dev/null @@ -1,35 +0,0 @@ -//#Patterns: implicitly_unwrapped_optional - -//#Issue: {"severity": "Info", "line": 15, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 31, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "implicitly_unwrapped_optional"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "implicitly_unwrapped_optional"} - - let label: UILabel! - - let IBOutlet: UILabel! - - let labels: [UILabel!] - - var ints: [Int!] = [42, nil, 42] - - let label: IBOutlet! - - let int: Int! = 42 - - let int: Int! = nil - - var int: Int! = 42 - - let int: ImplicitlyUnwrappedOptional - - let collection: AnyCollection - - func foo(int: Int!) {} diff --git a/src/main/resources/docs/tests/large_tuple.swift b/src/main/resources/docs/tests/large_tuple.swift deleted file mode 100644 index c9c2ab2..0000000 --- a/src/main/resources/docs/tests/large_tuple.swift +++ /dev/null @@ -1,50 +0,0 @@ -//#Patterns: large_tuple - -//#Issue: {"severity": "Info", "line": 17, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 41, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "large_tuple"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "large_tuple"} - - let foo: (Int, Int, Int) - - - let foo: (start: Int, end: Int, value: String) - - - let foo: (Int, (Int, Int, Int)) - - - func foo(bar: (Int, Int, Int)) - - - func foo() -> (Int, Int, Int) - - - func foo() -> (Int, Int, Int) {} - - - func foo(bar: String) -> (Int, Int, Int) - - - func foo(bar: String) -> (Int, Int, Int) {} - - - func foo() throws -> (Int, Int, Int) - - - func foo() throws -> (Int, Int, Int) {} - - - func foo() throws -> (Int, ↓(String, String, String), Int) {} - - - func getDictionaryAndInt() -> (Dictionary, Int)? diff --git a/src/main/resources/docs/tests/legacy_cggeometry_functions.swift b/src/main/resources/docs/tests/legacy_cggeometry_functions.swift deleted file mode 100644 index 13805dc..0000000 --- a/src/main/resources/docs/tests/legacy_cggeometry_functions.swift +++ /dev/null @@ -1,62 +0,0 @@ -//#Patterns: legacy_cggeometry_functions - -//#Issue: {"severity": "Info", "line": 24, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 36, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 48, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 52, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 58, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 60, "patternId": "legacy_cggeometry_functions"} -//#Issue: {"severity": "Info", "line": 62, "patternId": "legacy_cggeometry_functions"} - - CGRectGetWidth(rect) - - CGRectGetHeight(rect) - - CGRectGetMinX(rect) - - CGRectGetMidX(rect) - - CGRectGetMaxX(rect) - - CGRectGetMinY(rect) - - CGRectGetMidY(rect) - - CGRectGetMaxY(rect) - - CGRectIsNull(rect) - - CGRectIsEmpty(rect) - - CGRectIsInfinite(rect) - - CGRectStandardize(rect) - - CGRectIntegral(rect) - - CGRectInset(rect, 10, 5) - - CGRectOffset(rect, -2, 8.3) - - CGRectUnion(rect1, rect2) - - CGRectIntersection(rect1, rect2) - - CGRectContainsRect(rect1, rect2) - - CGRectContainsPoint(rect, point) - - CGRectIntersectsRect(rect1, rect2) diff --git a/src/main/resources/docs/tests/legacy_constant.swift b/src/main/resources/docs/tests/legacy_constant.swift deleted file mode 100644 index ce1de6e..0000000 --- a/src/main/resources/docs/tests/legacy_constant.swift +++ /dev/null @@ -1,32 +0,0 @@ -//#Patterns: legacy_constant - -//#Issue: {"severity": "Info", "line": 14, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "legacy_constant"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "legacy_constant"} - - CGRectInfinite - - CGPointZero - - CGRectZero - - CGSizeZero - - NSZeroPoint - - NSZeroRect - - NSZeroSize - - CGRectNull - - CGFloat(M_PI) - - Float(M_PI) diff --git a/src/main/resources/docs/tests/legacy_constructor.swift b/src/main/resources/docs/tests/legacy_constructor.swift deleted file mode 100644 index ed5af78..0000000 --- a/src/main/resources/docs/tests/legacy_constructor.swift +++ /dev/null @@ -1,62 +0,0 @@ -//#Patterns: legacy_constructor - -//#Issue: {"severity": "Info", "line": 24, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 36, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 48, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 52, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 58, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 60, "patternId": "legacy_constructor"} -//#Issue: {"severity": "Info", "line": 62, "patternId": "legacy_constructor"} - - CGPointMake(10, 10) - - CGPointMake(xVal, yVal) - - CGSizeMake(10, 10) - - CGSizeMake(aWidth, aHeight) - - CGRectMake(0, 0, 10, 10) - - CGRectMake(xVal, yVal, width, height) - - CGVectorMake(10, 10) - - CGVectorMake(deltaX, deltaY) - - NSMakePoint(10, 10) - - NSMakePoint(xVal, yVal) - - NSMakeSize(10, 10) - - NSMakeSize(aWidth, aHeight) - - NSMakeRect(0, 0, 10, 10) - - NSMakeRect(xVal, yVal, width, height) - - NSMakeRange(10, 1) - - NSMakeRange(loc, len) - - UIEdgeInsetsMake(0, 0, 10, 10) - - UIEdgeInsetsMake(top, left, bottom, right) - - NSEdgeInsetsMake(0, 0, 10, 10) - - NSEdgeInsetsMake(top, left, bottom, right) diff --git a/src/main/resources/docs/tests/legacy_nsgeometry_functions.swift b/src/main/resources/docs/tests/legacy_nsgeometry_functions.swift deleted file mode 100644 index 0e72904..0000000 --- a/src/main/resources/docs/tests/legacy_nsgeometry_functions.swift +++ /dev/null @@ -1,65 +0,0 @@ -//#Patterns: legacy_nsgeometry_functions - -//#Issue: {"severity": "Info", "line": 25, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 31, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 37, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 39, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 41, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 43, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 45, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 49, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 51, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 53, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 55, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 57, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 59, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 61, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 63, "patternId": "legacy_nsgeometry_functions"} -//#Issue: {"severity": "Info", "line": 65, "patternId": "legacy_nsgeometry_functions"} - - NSWidth(rect) - - NSHeight(rect) - - NSMinX(rect) - - NSMidX(rect) - - NSMaxX(rect) - - NSMinY(rect) - - NSMidY(rect) - - NSMaxY(rect) - - NSEqualRects(rect1, rect2) - - NSEqualSizes(size1, size2) - - NSEqualPoints(point1, point2) - - NSEdgeInsetsEqual(insets2, insets2) - - NSIsEmptyRect(rect) - - NSIntegralRect(rect) - - NSInsetRect(rect, 10, 5) - - NSOffsetRect(rect, -2, 8.3) - - NSUnionRect(rect1, rect2) - - NSIntersectionRect(rect1, rect2) - - NSContainsRect(rect1, rect2) - - NSPointInRect(rect, point) - - NSIntersectsRect(rect1, rect2) diff --git a/src/main/resources/docs/tests/mark.swift b/src/main/resources/docs/tests/mark.swift deleted file mode 100644 index 1301746..0000000 --- a/src/main/resources/docs/tests/mark.swift +++ /dev/null @@ -1,62 +0,0 @@ -//#Patterns: mark - -//#Issue: {"severity": "Info", "line": 24, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 36, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 48, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 52, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 58, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 59, "patternId": "mark"} -//#Issue: {"severity": "Info", "line": 61, "patternId": "mark"} - - //MARK: bad - - // MARK:bad - - //MARK:bad - - // MARK: bad - - // MARK: bad - - // MARK: -bad - - // MARK:- bad - - // MARK:-bad - - //MARK: - bad - - //MARK:- bad - - //MARK: -bad - - //MARK:-bad - - //Mark: bad - - // Mark: bad - - // MARK bad - - //MARK bad - - // MARK - bad - - //MARK:- Top-Level bad mark - //MARK:- Another bad mark - struct MarkTest {} - // MARK:- Bad mark - extension MarkTest {} diff --git a/src/main/resources/docs/tests/multiline_parameters.swift b/src/main/resources/docs/tests/multiline_parameters.swift deleted file mode 100644 index 9ec4694..0000000 --- a/src/main/resources/docs/tests/multiline_parameters.swift +++ /dev/null @@ -1,116 +0,0 @@ -//#Patterns: multiline_parameters - -//#Issue: {"severity": "Info", "line": 23, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 39, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 49, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 59, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 64, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 69, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 74, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 79, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 84, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 89, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 94, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 99, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 104, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 109, "patternId": "multiline_parameters"} -//#Issue: {"severity": "Info", "line": 114, "patternId": "multiline_parameters"} - - func foo(_ param1: Int, - param2: Int, param3: Int) -> (Int) -> Int { - return { x in x + param1 + param2 + param3 } - } - - protocol Foo { - func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - protocol Foo { - func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - protocol Foo { - static func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - protocol Foo { - static func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - protocol Foo { - class func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - protocol Foo { - class func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - enum Foo { - func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - enum Foo { - func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - enum Foo { - static func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - enum Foo { - static func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - struct Foo { - func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - struct Foo { - func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - struct Foo { - static func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - struct Foo { - static func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - class Foo { - func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - class Foo { - func foo(param1: Int, param2: Bool, - param3: [String]) { } - } - - class Foo { - class func foo(param1: Int, - param2: Bool, param3: [String]) { } - } - - class Foo { - class func foo(param1: Int, param2: Bool, - param3: [String]) { } - } diff --git a/src/main/resources/docs/tests/nesting.swift b/src/main/resources/docs/tests/nesting.swift deleted file mode 100644 index 8e8813a..0000000 --- a/src/main/resources/docs/tests/nesting.swift +++ /dev/null @@ -1,29 +0,0 @@ -//#Patterns: nesting - -//#Issue: {"severity": "Info", "line": 8, "patternId": "nesting"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "nesting"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "nesting"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "nesting"} - - class A { class B { class C {} } } - - - struct A { struct B { struct C {} } } - - - enum A { enum B { enum C {} } } - - - func func0() { - func func1() { - func func2() { - func func3() { - func func4() { func func5() { - func func6() { - } - } - } - } - } - } - } diff --git a/src/main/resources/docs/tests/nimble_operator.swift b/src/main/resources/docs/tests/nimble_operator.swift deleted file mode 100644 index 5261baf..0000000 --- a/src/main/resources/docs/tests/nimble_operator.swift +++ /dev/null @@ -1,38 +0,0 @@ -//#Patterns: nimble_operator - -//#Issue: {"severity": "Info", "line": 13, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 31, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "nimble_operator"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "nimble_operator"} - - expect(seagull.squawk).toNot(equal("Hi")) - - - expect(12).toNot(equal(10)) - - - expect(10).to(equal(10)) - - - expect(10).to(beGreaterThan(8)) - - - expect(10).to(beGreaterThanOrEqualTo(10)) - - - expect(10).to(beLessThan(11)) - - - expect(10).to(beLessThanOrEqualTo(10)) - - - expect(x).to(beIdenticalTo(x)) - - - expect(10) > 2 - expect(10).to(beGreaterThan(2)) diff --git a/src/main/resources/docs/tests/no_extension_access_modifier.swift b/src/main/resources/docs/tests/no_extension_access_modifier.swift deleted file mode 100644 index b601dff..0000000 --- a/src/main/resources/docs/tests/no_extension_access_modifier.swift +++ /dev/null @@ -1,19 +0,0 @@ -//#Patterns: no_extension_access_modifier - -//#Issue: {"severity": "Info", "line": 9, "patternId": "no_extension_access_modifier"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "no_extension_access_modifier"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "no_extension_access_modifier"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "no_extension_access_modifier"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "no_extension_access_modifier"} - - private extension String {} - - public - extension String {} - - open extension String {} - - internal extension String {} - - fileprivate extension String {} - diff --git a/src/main/resources/docs/tests/number_separator.swift b/src/main/resources/docs/tests/number_separator.swift deleted file mode 100644 index 3f949f5..0000000 --- a/src/main/resources/docs/tests/number_separator.swift +++ /dev/null @@ -1,74 +0,0 @@ -//#Patterns: number_separator - -//#Issue: {"severity": "Info", "line": 28, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 36, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 48, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 52, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 58, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 60, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 62, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 64, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 66, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 68, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 70, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 72, "patternId": "number_separator"} -//#Issue: {"severity": "Info", "line": 74, "patternId": "number_separator"} - - let foo = -10_0 - - let foo = -1000 - - let foo = -1000e2 - - let foo = -1000E2 - - let foo = -1__000 - - let foo = -1.0001 - - let foo = -1_000_000.000000_1 - - let foo = -1000000.000000_1 - - let foo = +10_0 - - let foo = +1000 - - let foo = +1000e2 - - let foo = +1000E2 - - let foo = +1__000 - - let foo = +1.0001 - - let foo = +1_000_000.000000_1 - - let foo = +1000000.000000_1 - - let foo = 10_0 - - let foo = 1000 - - let foo = 1000e2 - - let foo = 1000E2 - - let foo = 1__000 - - let foo = 1.0001 - - let foo = 1_000_000.000000_1 - - let foo = 1000000.000000_1 diff --git a/src/main/resources/docs/tests/object_literal.swift b/src/main/resources/docs/tests/object_literal.swift deleted file mode 100644 index 5639d4e..0000000 --- a/src/main/resources/docs/tests/object_literal.swift +++ /dev/null @@ -1,50 +0,0 @@ -//#Patterns: object_literal - -//#Issue: {"severity": "Info", "line": 20, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 36, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 48, "patternId": "object_literal"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "object_literal"} - - let image = UIImage(named: "foo") - - let color = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) - - let color = UIColor(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) - - let color = UIColor(white: 0.5, alpha: 1) - - let image = NSImage(named: "foo") - - let color = NSColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) - - let color = NSColor(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) - - let color = NSColor(white: 0.5, alpha: 1) - - let image = UIImage.init(named: "foo") - - let color = UIColor.init(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) - - let color = UIColor.init(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) - - let color = UIColor.init(white: 0.5, alpha: 1) - - let image = NSImage.init(named: "foo") - - let color = NSColor.init(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) - - let color = NSColor.init(red: 100 / 255.0, green: 50 / 255.0, blue: 0, alpha: 1) - - let color = NSColor.init(white: 0.5, alpha: 1) diff --git a/src/main/resources/docs/tests/opening_brace.swift b/src/main/resources/docs/tests/opening_brace.swift deleted file mode 100644 index 8586cec..0000000 --- a/src/main/resources/docs/tests/opening_brace.swift +++ /dev/null @@ -1,68 +0,0 @@ -//#Patterns: opening_brace - -//#Issue: {"severity": "Info", "line": 18, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 37, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 49, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 53, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 59, "patternId": "opening_brace"} -//#Issue: {"severity": "Info", "line": 65, "patternId": "opening_brace"} - - func abc(){ - } - - func abc() - { } - - [].map(){ $0 } - - [].map( { } ) - - if let a = b{ } - - while a == b{ } - - guard let a = b else{ } - - if - let a = b, - let c = d - where a == c{ } - - while - let a = b, - let c = d - where a == c{ } - - guard - let a = b, - let c = d - where a == c else{ } - - struct Rule{} - - - struct Rule - { - } - - - struct Rule - - { - } - - - struct Parent { - struct Child - { - let foo: Int - } - } diff --git a/src/main/resources/docs/tests/operator_usage_whitespace.swift b/src/main/resources/docs/tests/operator_usage_whitespace.swift deleted file mode 100644 index 0fc02a8..0000000 --- a/src/main/resources/docs/tests/operator_usage_whitespace.swift +++ /dev/null @@ -1,62 +0,0 @@ -//#Patterns: operator_usage_whitespace - -//#Issue: {"severity": "Info", "line": 19, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 31, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 37, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 43, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 49, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 52, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 55, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 58, "patternId": "operator_usage_whitespace"} -//#Issue: {"severity": "Info", "line": 61, "patternId": "operator_usage_whitespace"} - - let foo = 1+2 - - - let foo = 1 + 2 - - - let foo = 1 + 2 - - - let foo = 1 + 2 - - - let foo=1↓+2 - - - let foo=1 + 2 - - - let foo=bar - - - let range = 1 ..< 3 - - - let foo = bar ?? 0 - - - let foo = bar??0 - - - let foo = bar != 0 - - - let foo = bar !== bar2 - - - let v8 = Int8(1) << 6 - - - let v8 = 1 << (6) - - - let v8 = 1 << (6) - let foo = 1 > 2 diff --git a/src/main/resources/docs/tests/operator_whitespace.swift b/src/main/resources/docs/tests/operator_whitespace.swift deleted file mode 100644 index b3aacdb..0000000 --- a/src/main/resources/docs/tests/operator_whitespace.swift +++ /dev/null @@ -1,25 +0,0 @@ -//#Patterns: operator_whitespace - -//#Issue: {"severity": "Info", "line": 10, "patternId": "operator_whitespace"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "operator_whitespace"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "operator_whitespace"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "operator_whitespace"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "operator_whitespace"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "operator_whitespace"} - - func <|(lhs: Int, rhs: Int) -> Int {} - - - func <|<(lhs: A, rhs: A) -> A {} - - - func <| (lhs: Int, rhs: Int) -> Int {} - - - func <|< (lhs: A, rhs: A) -> A {} - - - func <| (lhs: Int, rhs: Int) -> Int {} - - - func <|< (lhs: A, rhs: A) -> A {} diff --git a/src/main/resources/docs/tests/private_outlet.swift b/src/main/resources/docs/tests/private_outlet.swift deleted file mode 100644 index c3fdf97..0000000 --- a/src/main/resources/docs/tests/private_outlet.swift +++ /dev/null @@ -1,13 +0,0 @@ -//#Patterns: private_outlet - -//#Issue: {"severity": "Info", "line": 7, "patternId": "private_outlet"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "private_outlet"} - - class Foo { - @IBOutlet var label: UILabel? - } - - - class Foo { - @IBOutlet var label: UILabel! - } diff --git a/src/main/resources/docs/tests/redundant_discardable_let.swift b/src/main/resources/docs/tests/redundant_discardable_let.swift deleted file mode 100644 index 9cd24f8..0000000 --- a/src/main/resources/docs/tests/redundant_discardable_let.swift +++ /dev/null @@ -1,9 +0,0 @@ -//#Patterns: redundant_discardable_let - -//#Issue: {"severity": "Info", "line": 6, "patternId": "redundant_discardable_let"} -//#Issue: {"severity": "Info", "line": 9, "patternId": "redundant_discardable_let"} - - let _ = foo() - - - if _ = foo() { let _ = bar() } diff --git a/src/main/resources/docs/tests/redundant_nil_coalescing.swift b/src/main/resources/docs/tests/redundant_nil_coalescing.swift deleted file mode 100644 index abfa14c..0000000 --- a/src/main/resources/docs/tests/redundant_nil_coalescing.swift +++ /dev/null @@ -1,9 +0,0 @@ -//#Patterns: redundant_nil_coalescing - -//#Issue: {"severity": "Info", "line": 6, "patternId": "redundant_nil_coalescing"} -//#Issue: {"severity": "Info", "line": 9, "patternId": "redundant_nil_coalescing"} - - var myVar: Int? = nil; myVar ?? nil - - - var myVar: Int? = nil; myVar??nil diff --git a/src/main/resources/docs/tests/redundant_optional_initialization.swift b/src/main/resources/docs/tests/redundant_optional_initialization.swift deleted file mode 100644 index 8477089..0000000 --- a/src/main/resources/docs/tests/redundant_optional_initialization.swift +++ /dev/null @@ -1,17 +0,0 @@ -//#Patterns: redundant_optional_initialization - -//#Issue: {"severity": "Info", "line": 8, "patternId": "redundant_optional_initialization"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "redundant_optional_initialization"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "redundant_optional_initialization"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "redundant_optional_initialization"} - - var myVar: Int? = nil - - - var myVar: Optional = nil - - - var myVar: Int?=nil - - - var myVar: Optional=nil diff --git a/src/main/resources/docs/tests/redundant_string_enum_value.swift b/src/main/resources/docs/tests/redundant_string_enum_value.swift deleted file mode 100644 index 7485a78..0000000 --- a/src/main/resources/docs/tests/redundant_string_enum_value.swift +++ /dev/null @@ -1,21 +0,0 @@ -//#Patterns: redundant_string_enum_value - -//#Issue: {"severity": "Info", "line": 9, "patternId": "redundant_string_enum_value"} -//#Issue: {"severity": "Info", "line": 10, "patternId": "redundant_string_enum_value"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "redundant_string_enum_value"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "redundant_string_enum_value"} - - enum Numbers: String { - case one = "one" - case two = "two" - } - - - enum Numbers: String { - case one = "one", two = ↓"two" - } - - - enum Numbers: String { - case one, two = "two" - } diff --git a/src/main/resources/docs/tests/redundant_void_return.swift b/src/main/resources/docs/tests/redundant_void_return.swift deleted file mode 100644 index ead3abd..0000000 --- a/src/main/resources/docs/tests/redundant_void_return.swift +++ /dev/null @@ -1,21 +0,0 @@ -//#Patterns: redundant_void_return - -//#Issue: {"severity": "Info", "line": 8, "patternId": "redundant_void_return"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "redundant_void_return"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "redundant_void_return"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "redundant_void_return"} - - func foo() -> Void {} - - - protocol Foo { - func foo() -> Void - } - - - func foo() -> () {} - - - protocol Foo { - func foo() -> () - } diff --git a/src/main/resources/docs/tests/return_arrow_whitespace.swift b/src/main/resources/docs/tests/return_arrow_whitespace.swift deleted file mode 100644 index c62b57f..0000000 --- a/src/main/resources/docs/tests/return_arrow_whitespace.swift +++ /dev/null @@ -1,33 +0,0 @@ -//#Patterns: return_arrow_whitespace - -//#Issue: {"severity": "Info", "line": 12, "patternId": "return_arrow_whitespace"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "return_arrow_whitespace"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "return_arrow_whitespace"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "return_arrow_whitespace"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "return_arrow_whitespace"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "return_arrow_whitespace"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "return_arrow_whitespace"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "return_arrow_whitespace"} - - func abc()->Int {} - - - func abc()->[Int] {} - - - func abc()->(Int, Int) {} - - - func abc()-> Int {} - - - func abc() ->Int {} - - - func abc() -> Int {} - - - var abc = {(param: Int) ->Bool in } - - - var abc = {(param: Int)->Bool in } diff --git a/src/main/resources/docs/tests/shorthand_operator.swift b/src/main/resources/docs/tests/shorthand_operator.swift deleted file mode 100644 index cd3d248..0000000 --- a/src/main/resources/docs/tests/shorthand_operator.swift +++ /dev/null @@ -1,88 +0,0 @@ -//#Patterns: shorthand_operator - -//#Issue: {"severity": "Info", "line": 26, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 35, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 41, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 47, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 53, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 59, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 62, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 65, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 68, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 71, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 74, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 77, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 80, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 83, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 86, "patternId": "shorthand_operator"} -//#Issue: {"severity": "Info", "line": 88, "patternId": "shorthand_operator"} - - foo = foo - 1 - - - foo = foo - aVariable - - - foo = foo - bar.method() - - - foo.aProperty = foo.aProperty - 1 - - - self.aProperty = self.aProperty - 1 - - - foo = foo / 1 - - - foo = foo / aVariable - - - foo = foo / bar.method() - - - foo.aProperty = foo.aProperty / 1 - - - self.aProperty = self.aProperty / 1 - - - foo = foo + 1 - - - foo = foo + aVariable - - - foo = foo + bar.method() - - - foo.aProperty = foo.aProperty + 1 - - - self.aProperty = self.aProperty + 1 - - - foo = foo * 1 - - - foo = foo * aVariable - - - foo = foo * bar.method() - - - foo.aProperty = foo.aProperty * 1 - - - self.aProperty = self.aProperty * 1 - - - n = n + i / outputLength - - n = n - i / outputLength diff --git a/src/main/resources/docs/tests/statement_position.swift b/src/main/resources/docs/tests/statement_position.swift deleted file mode 100644 index b15e677..0000000 --- a/src/main/resources/docs/tests/statement_position.swift +++ /dev/null @@ -1,16 +0,0 @@ -//#Patterns: statement_position - -//#Issue: {"severity": "Info", "line": 8, "patternId": "statement_position"} -//#Issue: {"severity": "Info", "line": 10, "patternId": "statement_position"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "statement_position"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "statement_position"} - - }else if { - - } else { - - } - catch { - - } - catch { diff --git a/src/main/resources/docs/tests/switch_case_on_newline.swift b/src/main/resources/docs/tests/switch_case_on_newline.swift deleted file mode 100644 index 7094614..0000000 --- a/src/main/resources/docs/tests/switch_case_on_newline.swift +++ /dev/null @@ -1,58 +0,0 @@ -//#Patterns: switch_case_on_newline - -//#Issue: {"severity": "Info", "line": 14, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 39, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "switch_case_on_newline"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "switch_case_on_newline"} - - switch foo { - case 1: return true - } - - - switch foo { - case let value: return true - } - - - switch foo { - default: return true - } - - - switch foo { - case "a string": return false - } - - - switch foo { - case .myCase: return false // error from network - } - - - switch foo { - case let .myCase(value) where value > 10: return false - } - - - switch foo { - case #selector(aFunction(_:)): return false - - } - - - switch foo { - case let .myCase(value) - where value > 10: return false - } - - - switch foo { - case .first, - .second: return false - } diff --git a/src/main/resources/docs/tests/syntactic_sugar.swift b/src/main/resources/docs/tests/syntactic_sugar.swift deleted file mode 100644 index 8fb6bde..0000000 --- a/src/main/resources/docs/tests/syntactic_sugar.swift +++ /dev/null @@ -1,30 +0,0 @@ -//#Patterns: syntactic_sugar - -//#Issue: {"severity": "Info", "line": 14, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "syntactic_sugar"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "syntactic_sugar"} - - let x: Array - - let x: Dictionary - - let x: Optional - - let x: ImplicitlyUnwrappedOptional - - func x(a: Array, b: Int) -> [Int: Any] - - func x(a: [Int], b: Int) -> Dictionary - - func x(a: Array, b: Int) -> ↓Dictionary - - let x = Array.array(of: object) - - let x: Swift.Optional diff --git a/src/main/resources/docs/tests/todo.swift b/src/main/resources/docs/tests/todo.swift deleted file mode 100644 index 7463db7..0000000 --- a/src/main/resources/docs/tests/todo.swift +++ /dev/null @@ -1,33 +0,0 @@ -//#Patterns: todo - -//#Issue: {"severity": "Info", "line": 12, "patternId": "todo"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "todo"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "todo"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "todo"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "todo"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "todo"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "todo"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "todo"} - - // TODO: - - - // FIXME: - - - // TODO(note) - - - // FIXME(note) - - - /* FIXME: */ - - - /* TODO: */ - - - /** FIXME: */ - - - /** TODO: */ diff --git a/src/main/resources/docs/tests/trailing_comma.swift b/src/main/resources/docs/tests/trailing_comma.swift deleted file mode 100644 index aa3a26b..0000000 --- a/src/main/resources/docs/tests/trailing_comma.swift +++ /dev/null @@ -1,38 +0,0 @@ -//#Patterns: trailing_comma - -//#Issue: {"severity": "Info", "line": 13, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "trailing_comma"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "trailing_comma"} - - let foo = [1, 2, 3,] - - - let foo = [1, 2, 3, ] - - - let foo = [1, 2, 3 ,] - - - let foo = [1: 2, 2: 3, ] - - - struct Bar { - let foo = [1: 2, 2: 3, ] - } - - - let foo = [1, 2, 3,] + [4, 5, 6↓,] - - - let example = [ 1, - 2, - // 3, - ] - - let foo = ["אבג", "αβγ", "🇺🇸",] diff --git a/src/main/resources/docs/tests/trailing_semicolon.swift b/src/main/resources/docs/tests/trailing_semicolon.swift deleted file mode 100644 index d08f4b2..0000000 --- a/src/main/resources/docs/tests/trailing_semicolon.swift +++ /dev/null @@ -1,22 +0,0 @@ -//#Patterns: trailing_semicolon - -//#Issue: {"severity": "Info", "line": 9, "patternId": "trailing_semicolon"} -//#Issue: {"severity": "Info", "line": 12, "patternId": "trailing_semicolon"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "trailing_semicolon"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "trailing_semicolon"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "trailing_semicolon"} - - let a = 0; - - - let a = 0; - let b = 1 - - - let a = 0;; - - - let a = 0; ;; - - - let a = 0; ; ; diff --git a/src/main/resources/docs/tests/type_body_length.swift b/src/main/resources/docs/tests/type_body_length.swift deleted file mode 100644 index eb144ce..0000000 --- a/src/main/resources/docs/tests/type_body_length.swift +++ /dev/null @@ -1,619 +0,0 @@ -//#Patterns: type_body_length - -//#Issue: {"severity": "Info", "line": 7, "patternId": "type_body_length"} -//#Issue: {"severity": "Info", "line": 212, "patternId": "type_body_length"} -//#Issue: {"severity": "Info", "line": 417, "patternId": "type_body_length"} - - class Abc { - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - } - - - struct Abc { - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - } - - - enum Abc { - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - let abc = 0 - } diff --git a/src/main/resources/docs/tests/type_name.swift b/src/main/resources/docs/tests/type_name.swift deleted file mode 100644 index b7fddb5..0000000 --- a/src/main/resources/docs/tests/type_name.swift +++ /dev/null @@ -1,74 +0,0 @@ -//#Patterns: type_name - -//#Issue: {"severity": "Info", "line": 26, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 28, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 36, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 38, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 40, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 48, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 50, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 52, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 56, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 58, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 60, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 62, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 65, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 69, "patternId": "type_name"} -//#Issue: {"severity": "Info", "line": 73, "patternId": "type_name"} - - class myType {} - - class _MyType {} - - private class MyType_ {} - - class My {} - - class AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} - - struct myType {} - - struct _MyType {} - - private struct MyType_ {} - - struct My {} - - struct AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} - - enum myType {} - - enum _MyType {} - - private enum MyType_ {} - - enum My {} - - enum AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA {} - - typealias X = Void - - private typealias Foo_Bar = Void - - private typealias foo = Void - - typealias AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = Void - - protocol Foo { - associatedtype X - } - - protocol Foo { - associatedtype Foo_Bar: Equatable - } - - protocol Foo { - associatedtype AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - } diff --git a/src/main/resources/docs/tests/unused_closure_parameter.swift b/src/main/resources/docs/tests/unused_closure_parameter.swift deleted file mode 100644 index 46c93c0..0000000 --- a/src/main/resources/docs/tests/unused_closure_parameter.swift +++ /dev/null @@ -1,46 +0,0 @@ -//#Patterns: unused_closure_parameter - -//#Issue: {"severity": "Info", "line": 12, "patternId": "unused_closure_parameter"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "unused_closure_parameter"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "unused_closure_parameter"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "unused_closure_parameter"} -//#Issue: {"severity": "Info", "line": 32, "patternId": "unused_closure_parameter"} -//#Issue: {"severity": "Info", "line": 37, "patternId": "unused_closure_parameter"} -//#Issue: {"severity": "Info", "line": 41, "patternId": "unused_closure_parameter"} -//#Issue: {"severity": "Info", "line": 45, "patternId": "unused_closure_parameter"} - - [1, 2].map { number in - return 3 - } - - - [1, 2].map { number in - return numberWithSuffix - } - - - [1, 2].map { number in - return 3 // number - } - - - [1, 2].map { number in - return 3 "number" - } - - - [1, 2].something { number, idx in - return number - } - - - genericsFunc { (number: TypeA, idx: TypeB) in return idx - } - - - hoge(arg: num) { num in - } - - - fooFunc { 아 in - } diff --git a/src/main/resources/docs/tests/unused_enumerated.swift b/src/main/resources/docs/tests/unused_enumerated.swift deleted file mode 100644 index 53932a9..0000000 --- a/src/main/resources/docs/tests/unused_enumerated.swift +++ /dev/null @@ -1,17 +0,0 @@ -//#Patterns: unused_enumerated - -//#Issue: {"severity": "Info", "line": 8, "patternId": "unused_enumerated"} -//#Issue: {"severity": "Info", "line": 11, "patternId": "unused_enumerated"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "unused_enumerated"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "unused_enumerated"} - - for (_, foo) in bar.enumerated() { } - - - for (_, foo) in abc.bar.enumerated() { } - - - for (_, foo) in abc.something().enumerated() { } - - - for (idx, _) in bar.enumerated() { } diff --git a/src/main/resources/docs/tests/unused_optional_binding.swift b/src/main/resources/docs/tests/unused_optional_binding.swift deleted file mode 100644 index f0ca217..0000000 --- a/src/main/resources/docs/tests/unused_optional_binding.swift +++ /dev/null @@ -1,46 +0,0 @@ -//#Patterns: unused_optional_binding - -//#Issue: {"severity": "Info", "line": 13, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 21, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 25, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 33, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 37, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 42, "patternId": "unused_optional_binding"} -//#Issue: {"severity": "Info", "line": 46, "patternId": "unused_optional_binding"} - - if let _ = Foo.optionalValue { - } - - - if let a = Foo.optionalValue, let _ = Foo.optionalValue2 { - } - - - guard let a = Foo.optionalValue, let _ = Foo.optionalValue2 { - } - - - if let (first, second) = getOptionalTuple(), let _ = Foo.optionalValue { - } - - - if let (first, _) = getOptionalTuple(), let _ = Foo.optionalValue { - } - - - if let (_, second) = getOptionalTuple(), let _ = Foo.optionalValue { - } - - - if let (_, _, _) = getOptionalTuple(), let bar = Foo.optionalValue { - } - - - func foo() { - if let _ = bar { - } - - - if case .some(let _) = self {} diff --git a/src/main/resources/docs/tests/valid_ibinspectable.swift b/src/main/resources/docs/tests/valid_ibinspectable.swift deleted file mode 100644 index 98448c5..0000000 --- a/src/main/resources/docs/tests/valid_ibinspectable.swift +++ /dev/null @@ -1,55 +0,0 @@ -//#Patterns: valid_ibinspectable - -//#Issue: {"severity": "Info", "line": 14, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 24, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 34, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 39, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 44, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 49, "patternId": "valid_ibinspectable"} -//#Issue: {"severity": "Info", "line": 54, "patternId": "valid_ibinspectable"} - - class Foo { - @IBInspectable private let count: Int - } - - - class Foo { - @IBInspectable private var insets: UIEdgeInsets - } - - - class Foo { - @IBInspectable private var count = 0 - } - - - class Foo { - @IBInspectable private var count: Int? - } - - - class Foo { - @IBInspectable private var count: Int! - } - - - class Foo { - @IBInspectable private var x: ImplicitlyUnwrappedOptional - } - - - class Foo { - @IBInspectable private var count: Optional - } - - - class Foo { - @IBInspectable private var x: Optional - } - - - class Foo { - @IBInspectable private var x: ImplicitlyUnwrappedOptional - } diff --git a/src/main/resources/docs/tests/vertical_parameter_alignment.swift b/src/main/resources/docs/tests/vertical_parameter_alignment.swift deleted file mode 100644 index cabd4f8..0000000 --- a/src/main/resources/docs/tests/vertical_parameter_alignment.swift +++ /dev/null @@ -1,18 +0,0 @@ -//#Patterns: vertical_parameter_alignment - -//#Issue: {"severity": "Info", "line": 9, "patternId": "vertical_parameter_alignment"} -//#Issue: {"severity": "Info", "line": 13, "patternId": "vertical_parameter_alignment"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "vertical_parameter_alignment"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "vertical_parameter_alignment"} - - func validateFunction(_ file: File, kind: SwiftDeclarationKind, - dictionary: [String: SourceKitRepresentable]) { } - - - func validateFunction(_ file: File, kind: SwiftDeclarationKind, - dictionary: [String: SourceKitRepresentable]) { } - - - func validateFunction(_ file: File, - kind: SwiftDeclarationKind, - dictionary: [String: SourceKitRepresentable]) { } diff --git a/src/main/resources/docs/tests/vertical_parameter_alignment_on_call.swift b/src/main/resources/docs/tests/vertical_parameter_alignment_on_call.swift deleted file mode 100644 index 628e18d..0000000 --- a/src/main/resources/docs/tests/vertical_parameter_alignment_on_call.swift +++ /dev/null @@ -1,30 +0,0 @@ -//#Patterns: vertical_parameter_alignment_on_call - -//#Issue: {"severity": "Info", "line": 12, "patternId": "vertical_parameter_alignment_on_call"} -//#Issue: {"severity": "Info", "line": 15, "patternId": "vertical_parameter_alignment_on_call"} -//#Issue: {"severity": "Info", "line": 18, "patternId": "vertical_parameter_alignment_on_call"} -//#Issue: {"severity": "Info", "line": 19, "patternId": "vertical_parameter_alignment_on_call"} -//#Issue: {"severity": "Info", "line": 22, "patternId": "vertical_parameter_alignment_on_call"} -//#Issue: {"severity": "Info", "line": 27, "patternId": "vertical_parameter_alignment_on_call"} -//#Issue: {"severity": "Info", "line": 30, "patternId": "vertical_parameter_alignment_on_call"} - - foo(param1: 1, param2: bar - param3: false, param4: true) - - foo(param1: 1, param2: bar - param3: false, param4: true) - - foo(param1: 1, param2: bar - param3: false, - param4: true) - - foo(param1: 1, - param2: { _ in }) - - foo(param1: 1, - param2: { _ in - }, param3: 2, - param4: 0) - - foo(param1: 1, param2: { _ in }, - param3: false, param4: true) diff --git a/src/main/resources/docs/tests/vertical_whitespace.swift b/src/main/resources/docs/tests/vertical_whitespace.swift deleted file mode 100644 index 4859960..0000000 --- a/src/main/resources/docs/tests/vertical_whitespace.swift +++ /dev/null @@ -1,17 +0,0 @@ -//#Patterns: vertical_whitespace - -//#Issue: {"severity": "Info", "line": 10, "patternId": "vertical_whitespace"} -//#Issue: {"severity": "Info", "line": 16, "patternId": "vertical_whitespace"} - - let aaaa = 0 - - - - - struct AAAA {} - - - - - - class BBBB {} diff --git a/src/main/resources/docs/tests/void_return.swift b/src/main/resources/docs/tests/void_return.swift deleted file mode 100644 index 586b837..0000000 --- a/src/main/resources/docs/tests/void_return.swift +++ /dev/null @@ -1,32 +0,0 @@ -//#Patterns: void_return - -//#Issue: {"severity": "Info", "line": 11, "patternId": "void_return"} -//#Issue: {"severity": "Info", "line": 14, "patternId": "void_return"} -//#Issue: {"severity": "Info", "line": 17, "patternId": "void_return"} -//#Issue: {"severity": "Info", "line": 20, "patternId": "void_return"} -//#Issue: {"severity": "Info", "line": 23, "patternId": "void_return"} -//#Issue: {"severity": "Info", "line": 26, "patternId": "void_return"} -//#Issue: {"severity": "Info", "line": 29, "patternId": "void_return"} - - let abc: () -> () = {} - - - let abc: () -> (Void) = {} - - - let abc: () -> ( Void ) = {} - - - func foo(completion: () -> ()) - - - func foo(completion: () -> ( )) - - - func foo(completion: () -> (Void)) - - - let foo: (ConfigurationTests) -> () throws -> ()) - - -asd diff --git a/src/main/scala/codacy/Engine.scala b/src/main/scala/codacy/Engine.scala index 372dc83..733bbde 100755 --- a/src/main/scala/codacy/Engine.scala +++ b/src/main/scala/codacy/Engine.scala @@ -1,6 +1,6 @@ package codacy -import codacy.dockerApi.DockerEngine +import com.codacy.tools.scala.seed.DockerEngine import codacy.swiftlint.SwiftLint -object Engine extends DockerEngine(SwiftLint) +object Engine extends DockerEngine(SwiftLint)() diff --git a/src/main/scala/codacy/swiftlint/SwiftLint.scala b/src/main/scala/codacy/swiftlint/SwiftLint.scala index 3c50f0b..78610ba 100755 --- a/src/main/scala/codacy/swiftlint/SwiftLint.scala +++ b/src/main/scala/codacy/swiftlint/SwiftLint.scala @@ -2,11 +2,13 @@ package codacy.swiftlint import java.nio.file.{Path, Paths} -import codacy.docker.api._ -import codacy.docker.api.utils.ToolHelper -import codacy.docker.api.{Pattern, Result, Source, Tool} -import codacy.dockerApi.utils.{CommandRunner, FileHelper} +import com.codacy.plugins.api.results.{Pattern, Result, Tool} +import com.codacy.plugins.api.{ErrorMessage, Options, Source} +import com.codacy.tools.scala.seed.utils.{CommandRunner, FileHelper} +import com.codacy.tools.scala.seed.utils.ToolHelper._ import play.api.libs.json._ +import better.files._ +import com.codacy.plugins.api.results.Result.FileError import scala.util.{Failure, Properties, Success, Try} @@ -14,6 +16,7 @@ case class SwiftLintFile(rule_id: String, file: String, reason: String, line: In object SwiftLintFile { implicit val readsSwiftLintFile: Reads[SwiftLintFile] = new Reads[SwiftLintFile] { + def reads(json: JsValue): JsResult[SwiftLintFile] = { for { rule_id <- (json \ "rule_id").validate[String] @@ -27,96 +30,139 @@ object SwiftLintFile { object SwiftLint extends Tool { - private lazy val configFileNames = Set(".swiftlint.yml") + private lazy val nativeConfigFileNames = Set(".swiftlint.yml") - override def apply(source: Source.Directory, configuration: Option[List[Pattern.Definition]], - files: Option[Set[Source.File]], options: Map[Configuration.Key, Configuration.Value]) - (implicit specification: Tool.Specification): Try[List[Result]] = { - Try { + def deleteNativeConfigurationFiles(source: Source.Directory): Unit = { + File(source.path) + .walk() + .find(file => nativeConfigFileNames.contains(file.name)) + .foreach(_.delete()) + } - val path = Paths.get(source.path) - lazy val nativeConfig = FileHelper.findConfigurationFile(configFileNames, path).map(_.toString) - val filesToLint: Set[String] = ToolHelper.filesToLint(source, files) - val patternsToLintOpt: Option[List[codacy.docker.api.Pattern.Definition]] = ToolHelper.patternsToLint(configuration) + def listOfFilesToLint(files: Option[Set[Source.File]], source: Source.Directory): List[String] = { + files match { + case None => List(source.path) + case Some(paths) if paths.isEmpty => List(source.path) + case Some(paths) => paths.map(_.path).toList + } + } - val config = patternsToLintOpt.fold(Option.empty[String]) { - case patternsToLint if patternsToLint.nonEmpty => - Some(writeConfigFile(patternsToLint).toString) - } + def configsFromCodacyConfiguration( + configuration: Option[List[Pattern.Definition]] + )(implicit specification: Tool.Specification): Option[String] = { + val patternsToLintOpt = configuration.withDefaultParameters - val cfgOpt = config.orElse(nativeConfig) + patternsToLintOpt.map { patternsToLint => + writeConfigFile(patternsToLint).toString + } + } - val baseCmd = List("swiftlint", "lint", "--quiet", "--reporter", "json") + private def commandToRun(configOpt: Option[String], file: String): List[String] = { + val baseCmd = List("swiftlint", "lint", "--quiet", "--reporter", "json") - val command = cfgOpt match { - case Some(opt) => - baseCmd ++ List("--config", opt, "--path") ++ filesToLint - case None => baseCmd ++ List("--path") ++ filesToLint - } + val configCmd = configOpt match { + case Some(opt) => + baseCmd ++ List("--config", opt) + case None => baseCmd + } + configCmd :+ file + } - CommandRunner.exec(command, Some(path.toFile)) match { - case Right(resultFromTool) => - parseToolResult(path, resultFromTool.stdout) match { - case s@Success(_) => s - case Failure(e) => - val msg = - s""" - |${this.getClass.getSimpleName} exited with code ${resultFromTool.exitCode} - |command: ${command.mkString(" ")} - |message: ${e.getMessage} - |stdout: ${resultFromTool.stdout.mkString(Properties.lineSeparator)} - |stderr: ${resultFromTool.stderr.mkString(Properties.lineSeparator)} + private def runToolCommand( + command: List[String], + source: Source.Directory, + cfgOpt: Option[String] + ): Try[List[Result]] = { + CommandRunner.exec(command, Option(Paths.get(source.path).toFile)) match { + case Right(resultFromTool) => + parseToolResult(resultFromTool.stdout) match { + case s @ Success(_) => s + case Failure(e) => + val msg = + s""" + |${this.getClass.getSimpleName} exited with code ${resultFromTool.exitCode} + |command: ${command.mkString(" ")} + |message: ${e.getMessage} + |stdout: ${resultFromTool.stdout.mkString(Properties.lineSeparator)} + |stderr: ${resultFromTool.stderr.mkString(Properties.lineSeparator)} + |configFile: + |${cfgOpt.fold("")(p => scala.io.Source.fromFile(p).getLines().mkString("\n"))} """.stripMargin - Failure(new Exception(msg)) - } - case Left(e) => - Failure(e) + Failure(new Exception(msg)) + } + case Left(e) => + Failure(e) + } + } + + override def apply( + source: Source.Directory, + configuration: Option[List[Pattern.Definition]], + files: Option[Set[Source.File]], + options: Map[Options.Key, Options.Value] + )(implicit specification: Tool.Specification): Try[List[Result]] = { + Try { + + val filesToLint = listOfFilesToLint(files, source) + + val cfgOpt = configsFromCodacyConfiguration(configuration) + + filesToLint.flatMap { file => + val command: List[String] = commandToRun(cfgOpt, file) + + val fileCommandAnalysisResult = runToolCommand(command, source, cfgOpt) + fileCommandAnalysisResult match { + case Success(res) => res + case Failure(exception) => + List( + FileError(Source.File(file), Some(ErrorMessage(s"Failed to analyse file $file: ${exception.getMessage}"))) + ) + } } - }.flatten + } } private def writeConfigFile(patternsToLint: List[Pattern.Definition]): Path = { val rules = patternsToLint.map(_.patternId.toString) val content = - s"""whitelist_rules: + s"""only_rules: | - ${rules.mkString("\n - ")}\n """.stripMargin FileHelper.createTmpFile(content, ".swiftlint-ci", ".yml") } - private def parseToolResult(path: Path, output: List[String]): Try[List[Result]] = { + private def parseToolResult(output: List[String]): Try[List[Result]] = { Try(Json.parse(output.mkString)).flatMap(parseToolResult) } private def parseToolResult(outputJson: JsValue): Try[List[Result]] = { /* Example: - * [ - * { - * "rule_id": "mark", - * "reason": "MARK comment should be in valid format. e.g. '\/\/ MARK: ...' or '\/\/ MARK: - ...'", - * "character": "5", - * "file": "\/Users\/marlontojal\/Documents\/GitHub\/codacy-swiftlint\/src\/main\/resources\/docs\/tests\/mark.swift", - * "severity": "Warning", - * "type": "Mark", - * "line": "3" - * }, - * ... - * ] - */ - - Try((outputJson).as[List[SwiftLintFile]]).map { violations => - violations.flatMap { - case violation => - List( - Result.Issue( - Source.File(violation.file), - Result.Message(violation.reason), - Pattern.Id(violation.rule_id), - Source.Line(violation.line) - ) - ) - } - } - } + * [ + * { + * "rule_id": "mark", + * "reason": "MARK comment should be in valid format. e.g. '\/\/ MARK: ...' or '\/\/ MARK: - ...'", + * "character": "5", + * "file": "\/Users\/marlontojal\/Documents\/GitHub\/codacy-swiftlint\/src\/main\/resources\/docs\/tests\/mark.swift", + * "severity": "Warning", + * "type": "Mark", + * "line": "3" + * }, + * ... + * ] + */ + + Try(outputJson.as[List[SwiftLintFile]]).map { violations => + violations.flatMap { violation => + List( + Result.Issue( + Source.File(violation.file), + Result.Message(violation.reason), + Pattern.Id(violation.rule_id), + Source.Line(violation.line) + ) + ) + } + } + } }