diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100755 index 0000000..f24b5e5 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,60 @@ +version: 2.1 + +orbs: + codacy: codacy/base@12.0.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..0025cc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ -/RUNNING_PID -/logs/ -/project/*-shim.sbt -/project/project/ -/project/target/ -/target/ +target .idea .DS_Store +.metals +.bloop +.vscode +.bsp +metals.sbt \ No newline at end of file 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..bdeca1a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM codacy-swiftlint-dev as builder + +FROM ghcr.io/realm/swiftlint:0.54.0 + +COPY --from=builder /docs /docs +COPY target/native-image/codacy-swiftlint /workdir/ +RUN adduser --uid 2004 --disabled-password --gecos "" docker +USER docker +WORKDIR /src +ENTRYPOINT ["/workdir/codacy-swiftlint"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..e2450d1 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,13 @@ +FROM norionomura/swiftlint:0.54.0_swift-5.9 + +RUN apt-get update && apt-get install -y openjdk-8-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..602b802 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.14" -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.2", + "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.2", + "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..550affb --- /dev/null +++ b/doc-generator/src/main/scala/doc-generator.scala @@ -0,0 +1,95 @@ +import com.codacy.plugins.api._ +import com.codacy.plugins.api.results._ +import play.api.libs.json.Json + +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() + val description = lines.next() + 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..2a483a9 --- /dev/null +++ b/docs/description/accessibility_label_for_image.md @@ -0,0 +1,318 @@ +# 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 +
+ +## 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..5cad209 --- /dev/null +++ b/docs/description/accessibility_trait_for_button.md @@ -0,0 +1,317 @@ +# 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 +
+ +## 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..535ada2 --- /dev/null +++ b/docs/description/anonymous_argument_in_multiline_closure.md @@ -0,0 +1,56 @@ +# 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 +
+ +## 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..488427d --- /dev/null +++ b/docs/description/array_init.md @@ -0,0 +1,114 @@ +# 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 +
+ +## 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/attributes.md b/docs/description/attributes.md new file mode 100644 index 0000000..6ab8e6a --- /dev/null +++ b/docs/description/attributes.md @@ -0,0 +1,431 @@ +# 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 + + [] +
+ +## 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..6643655 --- /dev/null +++ b/docs/description/balanced_xctest_lifecycle.md @@ -0,0 +1,142 @@ +# 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"] +
+ +## 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..f1594f9 --- /dev/null +++ b/docs/description/blanket_disable_command.md @@ -0,0 +1,88 @@ +# Blanket Disable Command + +swiftlint:disable commands should be re-enabled before the end 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 + + [] +
+ +## 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 +``` \ 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..92c9b86 --- /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..75692d7 --- /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..a839f01 --- /dev/null +++ b/docs/description/class_delegate_protocol.md @@ -0,0 +1,91 @@ +# 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 +
+ +## 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: NSObjectProtocol {} +``` + +```swift +protocol FooDelegate where Self: BarDelegate {} +``` + +```swift +protocol FooDelegate where Self: AnyObject {} +``` + +```swift +protocol FooDelegate where Self: NSObjectProtocol {} +``` + +## Triggering Examples + +```swift +↓protocol FooDelegate {} +``` + +```swift +↓protocol FooDelegate: Bar {} +``` + +```swift +↓protocol FooDelegate where Self: StringProtocol {} +``` \ 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..e6752b6 --- /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..9f9270c --- /dev/null +++ b/docs/description/closure_body_length.md @@ -0,0 +1,770 @@ +# 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 +
+ +## 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..c2b456e --- /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..bb5ee5d --- /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..9cf56f6 --- /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..5857a4b --- /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..008716c --- /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..e634498 --- /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..6c879b3 --- /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..47ae9e7 --- /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 Platground 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..b96de6b --- /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..410a92e --- /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..455416a --- /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..1f6225d --- /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..7ad18a3 --- /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..bfdaccc --- /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..93be994 --- /dev/null +++ b/docs/description/contains_over_range_nil_comparison.md @@ -0,0 +1,54 @@ +# Contains over Range Comparision 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/control_statement.md b/docs/description/control_statement.md new file mode 100644 index 0000000..75723e5 --- /dev/null +++ b/docs/description/control_statement.md @@ -0,0 +1,150 @@ +# 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) {} +``` + +## 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..15de703 --- /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..99a052d --- /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..be3d535 --- /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 0: return 1 + case 0: return 1 + case 0: return 1 + case 0: return 1 + case 0: return 1 + case 0: return 1 + case 0: return 1 + case 0: 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..741eff0 --- /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..b1746a1 --- /dev/null +++ b/docs/description/description.json @@ -0,0 +1,1166 @@ +[ { + "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" : "anyobject_protocol", + "title" : "AnyObject Protocol", + "description" : "Prefer using `AnyObject` over `class` for class-only protocols", + "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" : "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 be re-enabled before the end 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 Comparision to Nil", + "description" : "Prefer `contains` over `range(of:) != nil` and `range(of:) == nil`", + "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" : "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" : "inert_defer", + "title" : "Inert Defer", + "description" : "If defer is at the end of its parent scope, it will be executed right where it is anyway", + "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_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_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" : "opening_brace", + "title" : "Opening Brace Spacing", + "description" : "Opening braces should be preceded by a single space and on the same line as the declaration", + "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_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_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_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_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_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" : "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_capture_list", + "title" : "Unused Capture List", + "description" : "Unused reference in a capture list should be removed", + "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_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..6402af4 --- /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..7e22cfb --- /dev/null +++ b/docs/description/discarded_notification_center_observer.md @@ -0,0 +1,91 @@ +# 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 +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(_ notif: Any) { + obs.append(notif) +} +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: { }) +] +``` + +## 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: { }) +} +``` \ 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..64f4f64 --- /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..112735d --- /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..794cdaf --- /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..3dbac3f --- /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..400fd66 --- /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..134f398 --- /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..5578e5b --- /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..4417934 --- /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..0ef2d68 --- /dev/null +++ b/docs/description/duplicate_imports.md @@ -0,0 +1,179 @@ +# 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() { +} +``` + +## Triggering Examples + +```swift +@_implementationOnly import A +↓@_implementationOnly import A + +``` + +```swift +@testable import A +↓@testable import A + +``` + +```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..9b06d71 --- /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..837ed2b --- /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..74290f7 --- /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..01f0e78 --- /dev/null +++ b/docs/description/empty_count.md @@ -0,0 +1,114 @@ +# Empty Count + +Prefer checking `isEmpty` over comparing `count` to zero + +* **Identifier:** empty_count +* **Enabled by default:** No +* **Supports autocorrection:** No +* **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 +``` + +## 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 +``` \ 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..10556c3 --- /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 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..4e4166e --- /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..2e285ad --- /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..8ea4f2c --- /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..77392df --- /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..8dd4bce --- /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..e450dc7 --- /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..18154cb --- /dev/null +++ b/docs/description/explicit_acl.md @@ -0,0 +1,164 @@ +# 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) + } + } +} +``` + +## Triggering Examples + +```swift +↓enum A {} +``` + +```swift +final ↓class B {} +``` + +```swift +internal struct C { ↓let d = 5 } +``` + +```swift +public struct C { ↓let d = 5 } +``` + +```swift +func a() {} +``` + +```swift +internal let a = 0 +↓func b() {} +``` + +```swift +extension Foo { + ↓func bar() {} +} +``` \ 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..ff06d6b --- /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..b49d8c2 --- /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..2fdec19 --- /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..9ba015b --- /dev/null +++ b/docs/description/explicit_top_level_acl.md @@ -0,0 +1,88 @@ +# 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 C {} +``` + +```swift +internal enum A { enum B {} } +``` + +```swift +internal final class Foo {} +``` + +```swift +internal +class Foo {} +``` + +```swift +internal func a() {} +``` + +```swift +extension A: Equatable {} +``` + +```swift +extension A {} +``` + +## Triggering Examples + +```swift +↓enum A {} +``` + +```swift +final ↓class B {} +``` + +```swift +↓struct C {} +``` + +```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..6eca641 --- /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..3b586b7 --- /dev/null +++ b/docs/description/extension_access_modifier.md @@ -0,0 +1,117 @@ +# 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 +public extension Foo { + var bar: Int { return 1 } + var baz: Int { return 1 } +} +``` + +```swift +extension Foo { + private bar: Int { return 1 } + private baz: Int { return 1 } +} +``` + +```swift +extension Foo { + open bar: Int { return 1 } + open baz: Int { return 1 } +} +``` + +```swift +extension Foo { + func setup() {} + public func update() {} +} +``` + +## 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 } +} +``` \ No newline at end of file diff --git a/docs/description/fallthrough.md b/docs/description/fallthrough.md new file mode 100644 index 0000000..b3e7582 --- /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..f54ba78 --- /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..2769a2b --- /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..88721e6 --- /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..6c79ea8 --- /dev/null +++ b/docs/description/file_name.md @@ -0,0 +1,58 @@ +# 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 + + "." +
\ 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..d7a6a74 --- /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..c8e63ce --- /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/first_where.md b/docs/description/first_where.md new file mode 100644 index 0000000..5b102bc --- /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..de9adeb --- /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..bce5582 --- /dev/null +++ b/docs/description/for_where.md @@ -0,0 +1,147 @@ +# 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 +for user in users { + if user.id == 1 { return true } +} +``` + +```swift +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 +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..b1d364e --- /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..aad410b --- /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..32cc2c8 --- /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..9ff8e15 --- /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..69b42ce --- /dev/null +++ b/docs/description/function_default_parameter_at_end.md @@ -0,0 +1,100 @@ +# 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 +
+ +## 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)) {} +``` + +## 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) {} +``` \ 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..795aad4 --- /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..26d1596 --- /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..7759a60 --- /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..81764e0 --- /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..0748be6 --- /dev/null +++ b/docs/description/identifier_name.md @@ -0,0 +1,214 @@ +# 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 +
+ +## Non Triggering Examples + +```swift +let myLet = 0 +``` + +```swift +var myVar = 0 +``` + +```swift +private let _myLet = 0 +``` + +```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 +class Foo { + static let Bar = 0 +} +``` + +```swift +class Foo { + static var Bar = 0 +} +``` + +## Triggering Examples + +```swift +↓let _myLet = 0 +``` + +```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 +``` \ 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..bb3b7ac --- /dev/null +++ b/docs/description/implicit_getter.md @@ -0,0 +1,301 @@ +# 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 +} +``` + +```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..b6479b0 --- /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..f697d07 --- /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..6521362 --- /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..4763e0a --- /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..1a67e28 --- /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..90a650f --- /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..7f14413 --- /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..bf4d07b --- /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..b99a4d4 --- /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..c9c899f --- /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..d5ba707 --- /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..f5268d5 --- /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..1344464 --- /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..bb30a1a --- /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..d3c7d7e --- /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..bd0e8b8 --- /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..3c8af76 --- /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..39c534c --- /dev/null +++ b/docs/description/legacy_objc_type.md @@ -0,0 +1,86 @@ +# 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 +
+ +## 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") +``` + +## 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..9c0c058 --- /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..2a45d16 --- /dev/null +++ b/docs/description/let_var_whitespace.md @@ -0,0 +1,187 @@ +# 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 +let a = 0 +var x = 1 + +x = 2 +``` + +```swift +a = 5 + +var x = 1 +``` + +```swift +struct X { + var a = 0 +} +``` + +```swift +let a = 1 + + 2 +let b = 5 +``` + +```swift +var x: Int { + return 0 +} +``` + +```swift +var x: Int { + let a = 0 + + return a +} +``` + +```swift +#if os(macOS) +let a = 0 +#endif +``` + +```swift +#warning("TODO: remove it") +let a = 0 +``` + +```swift +#error("TODO: remove it") +let a = 0 +``` + +```swift +@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 +@available(OSX, introduced: 10.6) +@available(*, deprecated) +var x = 0 +``` + +```swift +// swiftlint:disable superfluous_disable_command +// swiftlint:disable force_cast + +let x = bar as! Bar +``` + +```swift + @available(swift 4) + @UserDefault("param", defaultValue: true) + var isEnabled = true + + @Attribute + func f() {} +``` + +```swift +var x: Int { + let a = 0 + return a +} +``` + +## Triggering Examples + +```swift +var x = 1 +↓x = 2 +``` + +```swift + +a = 5 +↓var x = 1 +``` + +```swift +struct X { + let a + ↓func x() {} +} +``` + +```swift +var x = 0 +↓@objc func f() {} +``` + +```swift +var x = 0 +↓@objc + func f() {} +``` + +```swift +@objc func f() { +} +↓var x = 0 +``` + +```swift + struct S { + func f() {} + ↓@Wapper + let isNumber = false + @Wapper + var isEnabled = true + ↓func g() {} + } +``` \ 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..1bb7935 --- /dev/null +++ b/docs/description/line_length.md @@ -0,0 +1,94 @@ +# 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 +
+ +## 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..2236e67 --- /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..61c48fe --- /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..01bc6e8 --- /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..52c747a --- /dev/null +++ b/docs/description/mark.md @@ -0,0 +1,164 @@ +# 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 +// BOOKMARK +``` + +```swift +//BOOKMARK +``` + +```swift +// BOOKMARKS +``` + +```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:- 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..9d5adeb --- /dev/null +++ b/docs/description/missing_docs.md @@ -0,0 +1,123 @@ +# 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 +
+ +## 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 { + deinit {} +} +``` + +```swift +public extension A {} +``` + +```swift +/// docs +public class A { + 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 +/// docs +public class A { + public init(argument: String) {} +} +``` \ 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..70ac9c5 --- /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..0f98592 --- /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..e09564d --- /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..3e973f6 --- /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..28d1f88 --- /dev/null +++ b/docs/description/multiline_literal_brackets.md @@ -0,0 +1,128 @@ +# 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 + ] +``` \ 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..68a31a8 --- /dev/null +++ b/docs/description/multiline_parameters.md @@ -0,0 +1,554 @@ +# 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 +func foo() { } +``` + +```swift +func foo(param1: Int) { } +``` + +```swift +protocol Foo { + func foo(param1: Int, + param2: Bool, + param3: [String]) { } +} +``` + +```swift +protocol Foo { + func foo( + param1: Int + ) { } +} +``` + +```swift +protocol Foo { + 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 +func ↓foo(param1: Int, param2: Bool) { } +``` + +```swift +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..cdd97c5 --- /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..eaf11a5 --- /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..f65f259 --- /dev/null +++ b/docs/description/nesting.md @@ -0,0 +1,895 @@ +# 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 +
+ +## Non Triggering Examples + +```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: + 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 + class Example_0 { + func f_0() { + class Example_1 { + func f_1() { + func f_2() {} + } + } + } + } +``` + +```swift + class Example_0 { + func f_0() { + switch example { + case .exampleCase: + class Example_1 { + func f_1() { + func f_2() {} + } + } + default: + exampleFunc(closure: { + class Example_1 { + func f_1() { + func f_2() {} + } + } + }) + } + } + } +``` + +```swift + struct Example_0 { + func f_0() { + struct Example_1 { + func f_1() { + func f_2() {} + } + } + } + } +``` + +```swift + struct Example_0 { + func f_0() { + switch example { + case .exampleCase: + struct Example_1 { + func f_1() { + func f_2() {} + } + } + default: + exampleFunc(closure: { + struct Example_1 { + func f_1() { + func f_2() {} + } + } + }) + } + } + } +``` + +```swift + enum Example_0 { + func f_0() { + enum Example_1 { + func f_1() { + func f_2() {} + } + } + } + } +``` + +```swift + enum Example_0 { + func f_0() { + switch example { + case .exampleCase: + enum Example_1 { + func f_1() { + func f_2() {} + } + } + default: + exampleFunc(closure: { + enum Example_1 { + func f_1() { + func f_2() {} + } + } + }) + } + } + } +``` + +## Triggering Examples + +```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: + 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 + class Example_0 { + func f_0() { + class Example_1 { + func f_1() { + func f_2() { + ↓class Example_2 {} + ↓func f_3() {} + } + } + } + } + } +``` + +```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() {} + } + } + } + default: + exampleFunc(closure: { + class Example_1 { + func f_1() { + func f_2() { + ↓class Example_2 {} + ↓func f_3() {} + } + } + } + }) + } + } + } +``` + +```swift + struct Example_0 { + func f_0() { + struct Example_1 { + func f_1() { + func f_2() { + ↓struct Example_2 {} + ↓func f_3() {} + } + } + } + } + } +``` + +```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() {} + } + } + } + default: + exampleFunc(closure: { + struct Example_1 { + func f_1() { + func f_2() { + ↓struct Example_2 {} + ↓func f_3() {} + } + } + } + }) + } + } + } +``` + +```swift + enum Example_0 { + func f_0() { + enum Example_1 { + func f_1() { + func f_2() { + ↓enum Example_2 {} + ↓func f_3() {} + } + } + } + } + } +``` + +```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() {} + } + } + } + default: + exampleFunc(closure: { + enum Example_1 { + func f_1() { + func f_2() { + ↓enum Example_2 {} + ↓func f_3() {} + } + } + } + }) + } + } + } +``` \ 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..d1ffdce --- /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_extension_access_modifier.md b/docs/description/no_extension_access_modifier.md new file mode 100644 index 0000000..2233cf5 --- /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..d35b5b1 --- /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..e5c26bf --- /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..56a2371 --- /dev/null +++ b/docs/description/no_magic_numbers.md @@ -0,0 +1,178 @@ +# 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"] +
+ +## 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 +``` + +## 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 +Color.primary.opacity(isAnimate ? ↓0.1 : ↓1.5) +``` + +```swift + class MyTest: XCTestCase {} + extension NSObject { + let a = Int(↓3) + } +``` \ 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..2ba3538 --- /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_overridable_class_declaration.md b/docs/description/non_overridable_class_declaration.md new file mode 100644 index 0000000..2c95887 --- /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 overriden. 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..c860ada --- /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..0886207 --- /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..5e56c19 --- /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..c87c168 --- /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..57f6bae --- /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..6bf5d01 --- /dev/null +++ b/docs/description/number_separator.md @@ -0,0 +1,370 @@ +# 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 +let foo = -↓1.0001 +``` + +```swift +let foo = -↓1_000_000.000000_1 +``` + +```swift +let foo = -↓1000000.000000_1 +``` + +```swift +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 +let foo = +↓1.0001 +``` + +```swift +let foo = +↓1_000_000.000000_1 +``` + +```swift +let foo = +↓1000000.000000_1 +``` + +```swift +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 +let foo = ↓1.0001 +``` + +```swift +let foo = ↓1_000_000.000000_1 +``` + +```swift +let foo = ↓1000000.000000_1 +``` + +```swift +let foo = ↓6.2832e-6 +``` + +```swift +let foo: Double = -(↓100000) +``` + +```swift +let foo: Double = -(↓10.000000_1) +``` + +```swift +let foo: Double = -(↓123456 / ↓447.214214) +``` + +```swift +let foo: Double = +(↓100000) +``` + +```swift +let foo: Double = +(↓10.000000_1) +``` + +```swift +let foo: Double = +(↓123456 / ↓447.214214) +``` + +```swift +let foo: Double = (↓100000) +``` + +```swift +let foo: Double = (↓10.000000_1) +``` + +```swift +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..21b0e02 --- /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/opening_brace.md b/docs/description/opening_brace.md new file mode 100644 index 0000000..14310ae --- /dev/null +++ b/docs/description/opening_brace.md @@ -0,0 +1,248 @@ +# Opening Brace Spacing + +Opening braces should be preceded by a single space and on the same line as the declaration + +* **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 +
+ 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 +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 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 { + {} +} +``` + +## Triggering Examples + +```swift +func abc()↓{ +} +``` + +```swift +func abc() + ↓{ } +``` + +```swift +func abc(a: A + b: B) +↓{ +``` + +```swift +[].map()↓{ $0 } +``` + +```swift +[].map( ↓{ } ) +``` + +```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 +// Get the current thread's TLS pointer. On first call for a given thread, +// creates and initializes a new one. +internal static func getPointer() + -> UnsafeMutablePointer<_ThreadLocalStorage> +{ // <- here + return _swift_stdlib_threadLocalStorageGet().assumingMemoryBound( + to: _ThreadLocalStorage.self) +} +``` + +```swift +func run_Array_method1x(_ N: Int) { + let existentialArray = array! + for _ in 0 ..< N * 100 { + for elt in existentialArray { + if !elt.doIt() { + fatalError("expected true") + } + } + } +} + +func run_Array_method2x(_ N: Int) { + +} +``` + +```swift + class TestFile { + func problemFunction() { + #if DEBUG + #endif + } + + func openingBraceViolation() + ↓{ + print("Brackets") + } + } +``` \ 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..cfb12a8 --- /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..eb3ef4f --- /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_enum_case_matching.md b/docs/description/optional_enum_case_matching.md new file mode 100644 index 0000000..9f82d14 --- /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..33d15ad --- /dev/null +++ b/docs/description/orphaned_doc_comment.md @@ -0,0 +1,66 @@ +# 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! +``` \ 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..82f0768 --- /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..dc93ac9 --- /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..630515c --- /dev/null +++ b/docs/description/pattern_matching_keywords.md @@ -0,0 +1,144 @@ +# 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 +} +``` + +## 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 .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..3037d52 --- /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_nimble.md b/docs/description/prefer_nimble.md new file mode 100644 index 0000000..8c234e3 --- /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..d980281 --- /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..3233887 --- /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_zero_over_explicit_init.md b/docs/description/prefer_zero_over_explicit_init.md new file mode 100644 index 0000000..cd95a5b --- /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..5da3e1a --- /dev/null +++ b/docs/description/prefixed_toplevel_constant.md @@ -0,0 +1,160 @@ +# 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 +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..0dfc9c3 --- /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..d039321 --- /dev/null +++ b/docs/description/private_outlet.md @@ -0,0 +1,98 @@ +# 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 +class Foo { @IBOutlet private(set) var label: UILabel? } +``` + +```swift +class Foo { @IBOutlet private(set) var label: UILabel! } +``` + +```swift +class Foo { @IBOutlet weak private(set) var label: UILabel? } +``` + +```swift +class Foo { @IBOutlet private(set) weak var label: UILabel? } +``` + +```swift +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..072b373 --- /dev/null +++ b/docs/description/private_over_fileprivate.md @@ -0,0 +1,96 @@ +# 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 + enum MyEnum {} +``` + +```swift +open extension + String {} +``` + +```swift +internal extension String {} +``` + +```swift +extension String { + fileprivate func Something(){} +} +``` + +```swift +class MyClass { + fileprivate let myInt = 4 +} +``` + +```swift +class MyClass { + fileprivate(set) var myInt = 4 +} +``` + +```swift +struct Outter { + struct Inter { + fileprivate struct Inner {} + } +} +``` + +## Triggering Examples + +```swift +↓fileprivate enum MyEnum {} +``` + +```swift +↓fileprivate class MyClass { + fileprivate(set) var myInt = 4 +} +``` \ 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..1667bdb --- /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..6bbe95c --- /dev/null +++ b/docs/description/private_swiftui_state.md @@ -0,0 +1,226 @@ +# Private SwiftUI State Properties + +SwiftUI state properties should be private + +* **Identifier:** private_swiftui_state +* **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 +struct MyApp: App { + @State private var isPlaying: Bool = false +} +``` + +```swift +struct MyScene: Scene { + @State private var isPlaying: Bool = false +} +``` + +```swift +struct ContentView: View { + @State private var isPlaying: Bool = false +} +``` + +```swift +struct ContentView: View { + @State fileprivate 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 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 ↓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() +} +``` \ 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..5bb6154 --- /dev/null +++ b/docs/description/private_unit_test.md @@ -0,0 +1,139 @@ +# 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"] +
+ regex + + "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..057e5c0 --- /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..d7e2da4 --- /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..c6dcd36 --- /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..8524a23 --- /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..4727ded --- /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..b5e8605 --- /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..95e3cd0 --- /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..2e9ec85 --- /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..1f49703 --- /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..b7fc9a2 --- /dev/null +++ b/docs/description/redundant_discardable_let.md @@ -0,0 +1,62 @@ +# 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 +
+ +## 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() +``` + +## Triggering Examples + +```swift +↓let _ = foo() +``` + +```swift +if _ = foo() { ↓let _ = bar() } +``` \ 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..17b87ca --- /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..4439b43 --- /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..a790d2b --- /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..adf6716 --- /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_set_access_control.md b/docs/description/redundant_set_access_control.md new file mode 100644 index 0000000..7bce61b --- /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..fb13d06 --- /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..11f37cf --- /dev/null +++ b/docs/description/redundant_type_annotation.md @@ -0,0 +1,105 @@ +# 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 +
+ +## Non Triggering Examples + +```swift +var url = URL() +``` + +```swift +var url: CustomStringConvertible = URL() +``` + +```swift +@IBInspectable var color: UIColor = UIColor.white +``` + +```swift +enum Direction { + case up + case down +} + +var direction: Direction = .up +``` + +```swift +enum Direction { + case up + case down +} + +var direction = Direction.up +``` + +## 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 alphanumerics↓: CharacterSet = CharacterSet.alphanumerics +``` + +```swift +class ViewController: UIViewController { + func someMethod() { + let myVar↓: Int = Int(5) + } +} +``` + +```swift +var isEnabled↓: Bool = true +``` + +```swift +enum Direction { + case up + case down +} + +var direction↓: Direction = Direction.up +``` \ 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..2997019 --- /dev/null +++ b/docs/description/redundant_void_return.md @@ -0,0 +1,106 @@ +# 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 +
+ +## 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) + } +} +``` + +## Triggering Examples + +```swift +func foo()↓ -> Void {} +``` + +```swift +protocol Foo { + func foo()↓ -> Void +} +``` + +```swift +func foo()↓ -> () {} +``` + +```swift +func foo()↓ -> ( ) {} +``` + +```swift +protocol Foo { + func foo()↓ -> () +} +``` \ 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..f1578bb --- /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..774c0c6 --- /dev/null +++ b/docs/description/required_enum_case.md @@ -0,0 +1,106 @@ +# 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 +enum MyNetworkResponse: String, NetworkResponsable { + case success, error, notConnected +} +``` + +```swift +enum MyNetworkResponse: String, NetworkResponsable { + case success, error, notConnected(error: Error) +} +``` + +```swift +enum MyNetworkResponse: String, NetworkResponsable { + case success + case error + case notConnected +} +``` + +```swift +enum MyNetworkResponse: String, NetworkResponsable { + case success + case error + case notConnected(error: Error) +} +``` + +## Triggering Examples + +```swift +↓enum MyNetworkResponse: String, NetworkResponsable { + case success, error +} +``` + +```swift +↓enum MyNetworkResponse: String, NetworkResponsable { + case success, error +} +``` + +```swift +↓enum MyNetworkResponse: String, NetworkResponsable { + case success + case error +} +``` + +```swift +↓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..82a8a13 --- /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..6d37d7d --- /dev/null +++ b/docs/description/return_value_from_void_function.md @@ -0,0 +1,290 @@ +# 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:** No +* **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 + } +``` + +## 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..23ca01c --- /dev/null +++ b/docs/description/self_binding.md @@ -0,0 +1,94 @@ +# 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 +if let this = self { return } +``` + +```swift +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 +if let ↓self = self { return } +``` + +```swift +guard let ↓self = self else { return } +``` + +```swift +if let ↓self { return } +``` + +```swift +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..332940f --- /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_operator.md b/docs/description/shorthand_operator.md new file mode 100644 index 0000000..1fe2682 --- /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..270966d --- /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..c111365 --- /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..dfb7a90 --- /dev/null +++ b/docs/description/sorted_enum_cases.md @@ -0,0 +1,102 @@ +# 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 a, b, c +} +``` + +```swift +enum foo { + case a + case b, c +} +``` + +```swift +enum foo { + case a(foo: Foo) + case b(String), c +} +``` + +```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, ↓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..47f16de --- /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..96f3fc5 --- /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..359d752 --- /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..433bf38 --- /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/strict_fileprivate.md b/docs/description/strict_fileprivate.md new file mode 100644 index 0000000..861c684 --- /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..f96dc7a --- /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..4746f93 --- /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..2a687f2 --- /dev/null +++ b/docs/description/superfluous_else.md @@ -0,0 +1,103 @@ +# 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:** No +* **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 + } +``` + +## 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 + } +``` \ 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..d51122a --- /dev/null +++ b/docs/description/switch_case_alignment.md @@ -0,0 +1,153 @@ +# 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 +
+ +## 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 + } +} +``` + +## 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 +} +``` \ 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..68c2a7e --- /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..0e006be --- /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..9630fe6 --- /dev/null +++ b/docs/description/test_case_accessibility.md @@ -0,0 +1,150 @@ +# 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 +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..d89bfdf --- /dev/null +++ b/docs/description/todo.md @@ -0,0 +1,70 @@ +# 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 +
+ +## 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..99a4c68 --- /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..67f8fd5 --- /dev/null +++ b/docs/description/trailing_closure.md @@ -0,0 +1,90 @@ +# Trailing Closure + +Trailing closure syntax should be used whenever possible + +* **Identifier:** trailing_closure +* **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_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 }()) +``` + +## 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 }) +``` \ 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..5c37989 --- /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..be7f563 --- /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..6ecc4d3 --- /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..4ca5400 --- /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..2515741 --- /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..7ded60e --- /dev/null +++ b/docs/description/type_contents_order.md @@ -0,0 +1,279 @@ +# 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], [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 + } + + // 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") + }, +} +``` + +## 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 */ } +} +``` \ 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..ef1f7c5 --- /dev/null +++ b/docs/description/type_name.md @@ -0,0 +1,239 @@ +# 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 +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..397614e --- /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..01e8e74 --- /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..839d07b --- /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..5ed0071 --- /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..99f89d8 --- /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:** 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: + 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..29719ef --- /dev/null +++ b/docs/description/unneeded_override.md @@ -0,0 +1,207 @@ +# 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 +
+ +## 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 { + 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 + }) + } +} +``` + +## 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..c232d69 --- /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..ba5f4e2 --- /dev/null +++ b/docs/description/unneeded_synthesized_initializer.md @@ -0,0 +1,385 @@ +# 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") + } +} +``` + +## 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 + } + } +} +``` \ 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..cbb0301 --- /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..c29073d --- /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..6cc9518 --- /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` immediatly 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..445f172 --- /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..3329def --- /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..971700d --- /dev/null +++ b/docs/description/unused_declaration.md @@ -0,0 +1,368 @@ +# 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 +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" +} +``` + +```swift +import Cocoa + +@NSApplicationMain +final class AppDelegate: NSObject, NSApplicationDelegate { + func applicationWillFinishLaunching(_ notification: Notification) {} + func applicationWillBecomeActive(_ notification: Notification) {} +} +``` + +```swift +import Foundation + +public final class Foo: NSObject { + @IBAction private func foo() {} +} +``` + +```swift +import Foundation + +public final class Foo: NSObject { + @objc func foo() {} +} +``` + +```swift +import Foundation + +public final class Foo: NSObject { + @IBInspectable private var innerPaddingWidth: Int { + set { self.backgroundView.innerPaddingWidth = newValue } + get { return self.backgroundView.innerPaddingWidth } + } +} +``` + +```swift +import Foundation + +public final class Foo: NSObject { + @IBOutlet private var bar: NSObject! { + set { fatalError() } + get { fatalError() } + } + + @IBOutlet private var baz: NSObject! { + willSet { print("willSet") } + } + + @IBOutlet private var buzz: NSObject! { + didSet { print("didSet") } + } +} +``` + +```swift + struct S { + var i: Int? = nil + func f() { + if let i { print(i) } + } + } + S().f() +``` + +## 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 +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 +import Cocoa + +@NSApplicationMain +final class AppDelegate: NSObject, NSApplicationDelegate { + func ↓appWillFinishLaunching(_ notification: Notification) {} + func applicationWillBecomeActive(_ notification: Notification) {} +} +``` + +```swift +import Cocoa + +final class ↓AppDelegate: NSObject, NSApplicationDelegate { + func applicationWillFinishLaunching(_ notification: Notification) {} + func applicationWillBecomeActive(_ notification: Notification) {} +} +``` + +```swift +import Foundation + +public final class Foo: NSObject { + @IBOutlet var ↓bar: NSObject! +} +``` + +```swift +import Foundation + +public final class Foo: NSObject { + @IBInspectable var ↓bar: String! +} +``` + +```swift +import Foundation + +final class Foo: NSObject {} +final class ↓Bar { + var ↓foo = Foo() +} +``` \ 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..f66e3a1 --- /dev/null +++ b/docs/description/unused_enumerated.md @@ -0,0 +1,82 @@ +# 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() {} +``` + +## 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() { } +``` \ 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..b2ed7d4 --- /dev/null +++ b/docs/description/unused_import.md @@ -0,0 +1,122 @@ +# 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 +import Foundation +let 👨‍👩‍👧‍👦 = #selector(NSArray.contains(_:)) +👨‍👩‍👧‍👦 == 👨‍👩‍👧‍👦 +``` + +## 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..2a56e05 --- /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_setter_value.md b/docs/description/unused_setter_value.md new file mode 100644 index 0000000..34e410c --- /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..8f5b27b --- /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..9fd9284 --- /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..6478010 --- /dev/null +++ b/docs/description/vertical_parameter_alignment_on_call.md @@ -0,0 +1,133 @@ +# 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 +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) +``` + +## 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) +``` \ 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..c94d47f --- /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..a90a0e5 --- /dev/null +++ b/docs/description/vertical_whitespace_between_cases.md @@ -0,0 +1,137 @@ +# 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 .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: + 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 low") + +case 5..<10: + print("x is high") + +default: + 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 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") + } +``` \ 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..81abc79 --- /dev/null +++ b/docs/description/vertical_whitespace_closing_braces.md @@ -0,0 +1,186 @@ +# 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 +print([ + 1 +]) +``` + +```swift +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 +print([ + 1 +↓ +]) +``` + +```swift +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..f64c110 --- /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..5df2320 --- /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..e8f306a --- /dev/null +++ b/docs/description/void_return.md @@ -0,0 +1,114 @@ +# 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 {} } +``` + +## 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..817b76b --- /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..30ede9c --- /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..7666933 --- /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..1a0be33 --- /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/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..8a92308 --- /dev/null +++ b/docs/patterns.json @@ -0,0 +1,1636 @@ +{ + "name" : "swiftlint", + "version" : "0.54.0", + "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" : "anyobject_protocol", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "patternId" : "array_init", + "level" : "Warning", + "category" : "ErrorProne", + "parameters" : [ ], + "languages" : [ ], + "enabled" : false + }, { + "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" : "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" : "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" : "inert_defer", + "level" : "Warning", + "category" : "ErrorProne", + "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_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_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" : "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_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_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_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_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_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" : "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_capture_list", + "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_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/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..875b706 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.9.2 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) + ) + ) + } + } + } }