├── .editorconfig
├── .eslintrc.yml
├── .gitignore
├── .prettierignore
├── .travis.yml
├── README.md
├── jest.eslint.config.js
├── jest.test.config.js
├── package.json
├── scripts
├── ci
│ └── download
├── dump
├── dump-clean
├── dump-doc
├── dump-js
├── dumper.js
└── run
├── src
├── index.js
├── parser
│ ├── index.js
│ ├── preprocessor.js
│ └── wrapper.js
└── printer
│ ├── builders.js
│ ├── chain.js
│ ├── generic.js
│ ├── index.js
│ ├── tokens.js
│ └── verbatim.js
├── tests
├── accessors
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── accessors.swift
│ └── jsfmt.spec.js
├── args
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── args.swift
│ └── jsfmt.spec.js
├── arrays
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── arrays.swift
│ └── jsfmt.spec.js
├── as
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── as.swift
│ └── jsfmt.spec.js
├── associatedtype
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── associatedtype.swift
│ └── jsfmt.spec.js
├── attributes
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── attributes.swift
│ └── jsfmt.spec.js
├── backtick
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── backtick.swift
│ └── jsfmt.spec.js
├── bugs
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── bugs.swift
│ ├── closure_with_parens.swift
│ └── jsfmt.spec.js
├── captures
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── captures.swift
│ └── jsfmt.spec.js
├── chains
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── chains.swift
│ └── jsfmt.spec.js
├── comments
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── chain.swift
│ ├── comments.swift
│ ├── jsfmt.spec.js
│ └── only.swift
├── composition
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── composition.swift
│ └── jsfmt.spec.js
├── continue
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── continue.swift
│ └── jsfmt.spec.js
├── defer
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── defer.swift
│ └── jsfmt.spec.js
├── deinit
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── deinit.swift
│ └── jsfmt.spec.js
├── dictionaries
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── dictionaries.swift
│ └── jsfmt.spec.js
├── dummy
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── dummy.swift
│ └── jsfmt.spec.js
├── enum
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── enum.swift
│ └── jsfmt.spec.js
├── extensions
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── extensions.swift
│ └── jsfmt.spec.js
├── for_in
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── for_in.swift
│ └── jsfmt.spec.js
├── func
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── func.swift
│ └── jsfmt.spec.js
├── function_calls
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── function_calls.swift
│ └── jsfmt.spec.js
├── generic_where_clause
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── generic_where_clause.swift
│ └── jsfmt.spec.js
├── generics
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── generics.swift
│ └── jsfmt.spec.js
├── guard
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── guard.swift
│ └── jsfmt.spec.js
├── if
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── if.swift
│ └── jsfmt.spec.js
├── if_config_decl
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── if_config_decl.swift
│ └── jsfmt.spec.js
├── ignore
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── ignore.swift
│ └── jsfmt.spec.js
├── import
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── import.swift
│ └── jsfmt.spec.js
├── init
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── init.swift
│ └── jsfmt.spec.js
├── is
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── is.swift
│ └── jsfmt.spec.js
├── is_type_pattern
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── is_type_pattern.swift
│ └── jsfmt.spec.js
├── keypath
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── keypath.swift
├── lazy
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── lazy.swift
├── operators
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── operators.swift
├── optional_chaining
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── optional_chaining.swift
├── protocols
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── protocols.swift
├── repeat_while_stmt
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── repeat_while_stmt.swift
├── specialize_expr
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── specialize_expr.swift
├── strings
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── strings.swift
├── subscript
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── subscript.swift
├── switch
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── switch.swift
├── ternary_expr
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── ternary_expr.swift
├── trailing_closure
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── trailing_closure.swift
├── try
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── try.swift
├── try_catch
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── try_catch.swift
├── tuple_expr
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── tuple_expr.swift
├── type_self
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── type_self.swift
├── typealias
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── typealias.swift
├── underscore
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── underscore.swift
├── while
│ ├── __snapshots__
│ │ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── while.swift
└── wildcard
│ ├── __snapshots__
│ └── jsfmt.spec.js.snap
│ ├── jsfmt.spec.js
│ └── wildcard.swift
├── tests_config
├── raw-serializer.js
└── run_spec.js
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [scripts/*]
12 | indent_size = 2
13 |
14 | [*.js]
15 | indent_size = 2
16 |
17 | [*.{snap,swift}]
18 | indent_size = 4
19 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | ---
2 | extends:
3 | - eslint:recommended
4 | - plugin:prettier/recommended
5 | - plugin:jest/recommended
6 | plugins:
7 | - import
8 | root: true
9 | env:
10 | es6: true
11 | node: true
12 | jest: true
13 | rules:
14 | curly: error
15 | import/no-extraneous-dependencies:
16 | - error
17 | - devDependencies: ["tests*/**", "scripts/**"]
18 | no-else-return: error
19 | no-inner-declarations: error
20 | no-unneeded-ternary: error
21 | no-useless-return: error
22 | no-var: error
23 | one-var:
24 | - error
25 | - never
26 | prefer-arrow-callback: error
27 | prefer-const: error
28 | react/no-deprecated: off
29 | strict: error
30 | symbol-description: error
31 | yoda:
32 | - error
33 | - never
34 | - exceptRange: true
35 | overrides:
36 | - files: "tests/**/*.js"
37 | rules:
38 | strict: off
39 | globals:
40 | run_spec: true
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /.vscode
3 | .DS_Store
4 | .idea
5 | *.swp
6 | /vendor
7 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | package.json
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | - 6
5 | - 8
6 | - 9
7 | cache:
8 | yarn: true
9 | apt: true
10 | directories:
11 | - node_modules
12 | - vendor
13 | addons:
14 | apt:
15 | packages:
16 | - clang
17 | - libicu-dev
18 | env:
19 | global:
20 | - TMPDIR=/tmp
21 | - PRETTIER_SWIFT_SWIFTC=vendor/swiftc
22 | install:
23 | - yarn install
24 | - scripts/ci/download
25 | - vendor/swiftc --version
26 | script:
27 | - yarn lint
28 | - yarn test -- --runInBand
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DEPRECATED
2 |
3 | `prettier/plugin-swift` is deprecated. It hasn’t been updated since early 2018, and the Swift community seems to have moved towards [Apple’s swift-format](https://github.com/apple/swift-format) and [Nick Lockwood’s SwiftFormat](https://github.com/nicklockwood/SwiftFormat) instead.
4 |
5 | We hope to someday have plugins for one or both of these tools, but the Prettier team has no current plans to develop such an integration. If you do make something, let us know by opening an issue on [the main Prettier repository](https://github.com/prettier/prettier/issues/new), and we will consider adding a link to this README.
6 |
7 | - - -
8 |
9 |
10 |

12 |

14 |
15 |
16 | Swift Plugin for the Opinionated Code Formatter
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | ## What does it do?
40 |
41 | **:warning: Warning :warning:** This plugin might eat your homework in its early stage.
42 | It also depends on [Swift's lib/Syntax](https://github.com/apple/swift/blob/master/lib/Syntax) which is
43 | [in flux](https://github.com/apple/swift/blob/master/lib/Syntax/Status.md).
44 | Please stage or commit your code before performing any in-place formatting.
45 |
46 | You can check out [how it formatted Artsy's Eidolon](https://github.com/sirlantis/eidolon/pull/1/files).
47 |
48 | ## Prerequisites
49 |
50 | You need one of the following:
51 |
52 | 1. A [snapshot from March 30, 2018 or later](https://swift.org/download/#snapshots),
53 | 2. a recent manual build from Swift's [`master`](https://github.com/apple/swift), or
54 | 3. Swift 4.2 (once it's available as a beta or released completely).
55 |
56 | Assuming you picked **(1)** please follow the
57 | [installation instructions](https://swift.org/download/#using-downloads),
58 | which recommend updating your `PATH` at the end:
59 |
60 | ```
61 | TOOLCHAIN=swift-DEVELOPMENT-SNAPSHOT-2018-03-30-a.xctoolchain
62 | export PATH=/Library/Developer/Toolchains/${TOOLCHAIN}/usr/bin/:"${PATH}"
63 | ```
64 |
65 | Alternatively you can pass the full path to the `swiftc` binary
66 | via the environment variable `PRETTIER_SWIFT_SWIFTC`:
67 |
68 | ```
69 | TOOLCHAIN=swift-DEVELOPMENT-SNAPSHOT-2018-03-30-a.xctoolchain
70 | export PRETTIER_SWIFT_SWIFTC=/Library/Developer/Toolchains/${TOOLCHAIN}/usr/bin/swiftc
71 | ```
72 |
73 | ## Contributing
74 |
75 | If you're interested in contributing to the development of Prettier for Swift, you can follow the [CONTRIBUTING guide from Prettier](https://github.com/prettier/prettier/blob/master/CONTRIBUTING.md), as it all applies to this repository too.
76 |
77 | To test it out on a Swift file:
78 |
79 | * Clone this repository.
80 | * Run `yarn`.
81 | * Create a file called `test.swift`.
82 | * Run `yarn prettier test.swift` to check the output.
83 |
84 | ## Install
85 |
86 | ```bash
87 | yarn add --dev --exact prettier prettier/plugin-swift
88 | ```
89 |
90 | ## Use
91 |
92 | ```bash
93 | prettier --write "**/*.swift"
94 | ```
95 |
96 | ## Maintainers
97 |
98 |
111 |
--------------------------------------------------------------------------------
/jest.eslint.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 | runner: "jest-runner-eslint",
5 | displayName: "lint",
6 | testMatch: ["/**/*.js"],
7 | testPathIgnorePatterns: ["node_modules/"]
8 | };
9 |
--------------------------------------------------------------------------------
/jest.test.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const ENABLE_COVERAGE = false; // !!process.env.CI;
4 |
5 | module.exports = {
6 | displayName: "test",
7 | setupFiles: ["/tests_config/run_spec.js"],
8 | snapshotSerializers: ["/tests_config/raw-serializer.js"],
9 | testRegex: "jsfmt\\.spec\\.js$|__tests__/.*\\.js$",
10 | testPathIgnorePatterns: ["tests/new_react", "tests/more_react"],
11 | collectCoverage: ENABLE_COVERAGE,
12 | collectCoverageFrom: ["src/**/*.js", "!/node_modules/"],
13 | transform: {}
14 | };
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@prettier/plugin-swift",
3 | "version": "0.0.0-development",
4 | "description": "Prettier Swift Plugin",
5 | "main": "src",
6 | "repository": "prettier/prettier-swift",
7 | "author": "Marcel Jackwerth <@sirlantis>",
8 | "deprecated": "Please consider using https://github.com/apple/swift-format or https://github.com/nicklockwood/SwiftFormat instead.",
9 | "license": "MIT",
10 | "files": [
11 | "src",
12 | "vendor"
13 | ],
14 | "engines": {
15 | "node": ">=6"
16 | },
17 | "dependencies": {
18 | "chalk": "2",
19 | "prettier": "prettier/prettier#1.11.1"
20 | },
21 | "devDependencies": {
22 | "eslint": "^4.14.0",
23 | "eslint-config-prettier": "^2.9.0",
24 | "eslint-plugin-import": "^2.8.0",
25 | "eslint-plugin-jest": "^21.5.0",
26 | "eslint-plugin-prettier": "^2.4.0",
27 | "jest": "^21.1.0",
28 | "jest-runner-eslint": "^0.3.0",
29 | "prettyjson": "^1.2.1"
30 | },
31 | "scripts": {
32 | "lint": "prettier src/**/*.js --list-different",
33 | "test": "jest",
34 | "prettier": "prettier --plugin=. --parser=swift"
35 | },
36 | "jest": {
37 | "projects": [
38 | "/jest.*.config.js"
39 | ]
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/scripts/ci/download:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 |
4 | VERSION_PREFIX=${BRANCH:-swift}
5 | VERSION_PREFIX=${VERSION_PREFIX//-branch/}
6 | BRANCH=${BRANCH:-development}
7 | VERSION=${VERSION_PREFIX}-DEVELOPMENT-SNAPSHOT-2018-03-30-a
8 | SERVER_PATH=https://swift.org/builds/${BRANCH}
9 |
10 | OS=${OS:-${OSTYPE}}
11 |
12 | case "$OS" in
13 | darwin*)
14 | SERVER_PATH_SUFFIX=xcode
15 | ARCHIVE_SUFFIX=-osx
16 | ARCHIVE_EXT=.pkg
17 | ;;
18 | linux*)
19 | if [ -z "${LSB_RELEASE:-}" ]; then
20 | LSB_RELEASE=$(lsb_release -r -s)
21 | fi
22 |
23 | SERVER_PATH_SUFFIX=ubuntu${LSB_RELEASE//./}
24 | ARCHIVE_SUFFIX=-ubuntu${LSB_RELEASE}
25 | ARCHIVE_EXT=.tar.gz
26 | ;;
27 | *)
28 | echo "Unsupported OS: $OS"
29 | exit 1
30 | ;;
31 | esac
32 |
33 | ARCHIVE_NAME=${VERSION}${ARCHIVE_SUFFIX}${ARCHIVE_EXT}
34 |
35 | CACHE_DIR=vendor
36 | SWIFTC=${CACHE_DIR}/swiftc
37 | SWIFTC_METADATA=${CACHE_DIR}/swiftc.metadata
38 |
39 | ARCHIVE_PATH=${TMPDIR}/${ARCHIVE_NAME}
40 |
41 | function download() {
42 | if [ -f "${ARCHIVE_PATH}" ]; then
43 | echo "Using existing archive at ${ARCHIVE_PATH}"
44 | return
45 | fi
46 |
47 | DOWNLOAD_URL=${SERVER_PATH}/${SERVER_PATH_SUFFIX}/${VERSION}/${ARCHIVE_NAME}
48 |
49 | echo "Downloading ${ARCHIVE_PATH}"
50 | echo " from ${DOWNLOAD_URL}"
51 |
52 | curl -o "${ARCHIVE_PATH}" "${DOWNLOAD_URL}"
53 | }
54 |
55 | function extract() {
56 | ARCHIVE_ENTRY=${VERSION}${ARCHIVE_SUFFIX}/usr/bin/swift
57 |
58 | pushd "${TMPDIR}"
59 | tar -xzf "${ARCHIVE_NAME}" "${ARCHIVE_ENTRY}"
60 | popd
61 |
62 | mkdir -p "${CACHE_DIR}"
63 | cp "${TMPDIR}/${ARCHIVE_ENTRY}" "${SWIFTC}"
64 | echo "${ARCHIVE_NAME}" > "${SWIFTC_METADATA}"
65 | }
66 |
67 | function check() {
68 | "${SWIFTC}" --version
69 | }
70 |
71 | if [ -f "${SWIFTC}" ]; then
72 | echo "Found cached binary at ${SWIFTC}"
73 |
74 | if [ -f "${SWIFTC_METADATA}" ]; then
75 | metadata=$(<${SWIFTC_METADATA})
76 |
77 | if [ "${ARCHIVE_NAME}" == "${metadata}" ]; then
78 | echo "Metadata matched expected ${ARCHIVE_NAME}"
79 | exit 0
80 | else
81 | echo "Metadata was ${metadata} (expected: ${ARCHIVE_NAME})"
82 | fi
83 | else
84 | echo "${SWIFTC_METADATA} did not exist."
85 | fi
86 | fi
87 |
88 | download
89 | extract
90 |
--------------------------------------------------------------------------------
/scripts/dump:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 |
4 | const fs = require("fs");
5 | const { emitSyntax } = require("../src/parser/wrapper");
6 | const dumper = require("./dumper");
7 |
8 | const text = fs.readFileSync(process.argv[2], "utf-8");
9 | const ast = emitSyntax(text);
10 |
11 | // eslint-disable-next-line no-console
12 | console.log(dumper(ast));
13 |
--------------------------------------------------------------------------------
/scripts/dump-clean:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 |
4 | const fs = require("fs");
5 | const prettierSwift = require("../src");
6 | const dumper = require("./dumper");
7 | const comments = require("prettier/src/main/comments");
8 | const { printDocToString } = require("prettier").doc.printer;
9 | const printAstToDoc = require("prettier/src/main/ast-to-doc");
10 |
11 | const opts = {
12 | printWidth: 140,
13 | tabWidth: 2,
14 | parser: prettierSwift.parsers.swift,
15 | printer: prettierSwift.printers.swift,
16 | locStart: prettierSwift.parsers.swift.locStart,
17 | locEnd: prettierSwift.parsers.swift.locEnd
18 | };
19 |
20 | let text = fs.readFileSync(process.argv[2], "utf-8");
21 | text = opts.parser.preprocess(text, opts);
22 | const ast = opts.parser.parse(text, opts);
23 |
24 | function attachComments(text, ast, opts) {
25 | const astComments = ast.comments;
26 | if (astComments) {
27 | delete ast.comments;
28 | comments.attach(astComments, ast, text, opts);
29 | }
30 | ast.tokens = [];
31 | opts.originalText = text.trimRight();
32 | return astComments;
33 | }
34 |
35 | attachComments(text, ast, opts);
36 |
37 | // eslint-disable-next-line no-console
38 | console.log(dumper(ast));
39 |
40 | printDocToString(printAstToDoc(ast, opts), opts).formatted;
41 |
--------------------------------------------------------------------------------
/scripts/dump-doc:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | scripts/run --debug-print-doc $@
3 |
--------------------------------------------------------------------------------
/scripts/dump-js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 |
4 | const fs = require("fs");
5 | const parse = require("prettier/src/language-js/parser-babylon");
6 | const dumper = require("./dumper");
7 |
8 | const text = fs.readFileSync(process.argv[2], "utf-8");
9 | const ast = parse(text);
10 |
11 | // eslint-disable-next-line no-console
12 | console.log(dumper(ast));
13 |
--------------------------------------------------------------------------------
/scripts/dumper.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { printDocToString } = require("prettier").doc.printer;
4 | const printAstToDoc = require("prettier/src/main/ast-to-doc");
5 | const {
6 | concat,
7 | hardline,
8 | join,
9 | indent,
10 | group,
11 | line,
12 | lineSuffix
13 | } = require("prettier").doc.builders;
14 |
15 | function genericPrint(path, options, print) {
16 | const node = path.getValue();
17 |
18 | if (Array.isArray(node)) {
19 | if (node.length === 0) {
20 | return "[]";
21 | }
22 |
23 | return concat([
24 | join(hardline, path.map(print).map(s => indent(concat(["- ", s]))))
25 | ]);
26 | } else if (node === null) {
27 | return "~";
28 | } else if (typeof node === "object") {
29 | let metadata;
30 |
31 | if (node.__location) {
32 | metadata = `${node.__location.startOffset}-${node.__location.endOffset}`;
33 | } else if (node.start && node.end) {
34 | metadata = `${node.start}-${node.end}`;
35 | }
36 |
37 | return concat([
38 | metadata ? lineSuffix(` // ${metadata}`) : "",
39 | join(
40 | hardline,
41 | Object.entries(node)
42 | .filter(
43 | entry => !["__location", "loc", "start", "end"].includes(entry[0])
44 | )
45 | .filter(entry => typeof entry[1] !== "undefined")
46 | .map(entry => {
47 | return group(
48 | indent(
49 | concat([
50 | entry[0],
51 | concat([":", line]),
52 | path.call(print, entry[0])
53 | ])
54 | )
55 | );
56 | })
57 | )
58 | ]);
59 | }
60 |
61 | return JSON.stringify(node);
62 | }
63 |
64 | const opts = {
65 | printWidth: 140,
66 | tabWidth: 2,
67 | printer: {
68 | print: genericPrint,
69 | willPrintOwnComments: () => {
70 | return true;
71 | }
72 | }
73 | };
74 |
75 | module.exports = ast => {
76 | return printDocToString(printAstToDoc(ast, opts), opts).formatted;
77 | };
78 |
--------------------------------------------------------------------------------
/scripts/run:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | node_modules/.bin/prettier --plugin . --parser swift --tab-width 4 $@
3 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const util = require("prettier/src/common/util");
4 | const { parse, preprocess } = require("./parser");
5 | const print = require("./printer");
6 |
7 | const languages = [
8 | {
9 | name: "Swift",
10 | parsers: ["swift"],
11 | extensions: [".swift"],
12 | tmScope: "source.swift",
13 | aceMode: "text",
14 | linguistLanguageId: 362,
15 | vscodeLanguageIds: ["swift"]
16 | }
17 | ];
18 |
19 | const parsers = {
20 | swift: {
21 | parse,
22 | preprocess,
23 | astFormat: "swift",
24 | locStart: n => n.__location.startOffset,
25 | locEnd: n => n.__location.endOffset
26 | }
27 | };
28 |
29 | function canAttachComment(node) {
30 | if (node.token) {
31 | return false;
32 | } else if (["StmtList", "DeclList"].includes(node.type)) {
33 | return !node.layout.length;
34 | } else if (node.type.endsWith("List")) {
35 | return false;
36 | }
37 |
38 | return !["SourceFile", "IfConfigDecl", "FunctionCallArgument"].includes(
39 | node.type
40 | );
41 | }
42 |
43 | function printComment(commentPath) {
44 | const comment = commentPath.getValue();
45 |
46 | switch (comment.type) {
47 | case "CommentBlock":
48 | return comment.originalValue;
49 | case "CommentLine":
50 | return comment.originalValue.trimRight();
51 | default:
52 | throw new Error("Not a valid comment: " + JSON.stringify(comment));
53 | }
54 | }
55 |
56 | const printers = {
57 | swift: {
58 | print,
59 | hasPrettierIgnore: util.hasIgnoreComment,
60 | canAttachComment,
61 | printComment,
62 | getCommentChildNodes,
63 | willPrintOwnComments
64 | }
65 | };
66 |
67 | function willPrintOwnComments() {
68 | return true;
69 | }
70 |
71 | function getCommentChildNodes(node) {
72 | return node.layout;
73 | }
74 |
75 | module.exports = {
76 | languages,
77 | printers,
78 | parsers
79 | };
80 |
--------------------------------------------------------------------------------
/src/parser/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const assert = require("assert");
4 |
5 | const { verbatimPrint } = require("../printer/verbatim");
6 | const { emitSyntax, checkVersion } = require("./wrapper");
7 | const preprocessor = require("./preprocessor");
8 | const { printToken } = require("../printer/tokens");
9 |
10 | function massage(node) {
11 | if (node.presence === "Missing") {
12 | return;
13 | }
14 |
15 | let {
16 | tokenKind: token,
17 | kind: type,
18 | value,
19 | text,
20 | layout,
21 | leadingTrivia,
22 | trailingTrivia
23 | } = node;
24 |
25 | if (token) {
26 | ({ kind: type, text } = token);
27 | token = true;
28 | }
29 |
30 | if (layout) {
31 | layout = layout
32 | .filter(v => v)
33 | .map(massage)
34 | .filter(v => v);
35 | }
36 |
37 | if (type === "UnknownDecl") {
38 | if (layout.some(n => n.type == "kw_extension")) {
39 | type = "_ExtensionDecl";
40 | } else if (layout.some(n => n.type == "kw_enum")) {
41 | type = "_EnumDecl";
42 |
43 | const rBrace = layout.pop();
44 | const decl = layout.pop();
45 | const lBrace = layout.pop();
46 |
47 | layout.push({
48 | type: "_EnumDeclBlock",
49 | layout: [lBrace, decl, rBrace]
50 | });
51 | } else if (layout.some(n => n.type == "kw_case")) {
52 | type = "_CaseDecl";
53 |
54 | const tokens = layout.splice(1);
55 | const elements = [];
56 | let currentElement = [];
57 | let currentInitializerClause;
58 |
59 | tokens.forEach(n => {
60 | if (n.type === "comma") {
61 | currentElement.push(n);
62 |
63 | elements.push({
64 | type: "_CaseDeclElement",
65 | layout: currentElement
66 | });
67 |
68 | currentElement = [];
69 | } else if (n.type == "equal") {
70 | currentInitializerClause = {
71 | type: "InitializerClause",
72 | layout: [n]
73 | };
74 | currentElement.push(currentInitializerClause);
75 | } else if (currentInitializerClause) {
76 | currentInitializerClause.layout.push(n);
77 | } else if (n.type === "Unknown") {
78 | currentElement.push({
79 | token: true,
80 | type: "identifier",
81 | text: verbatimPrint(n)
82 | });
83 | } else {
84 | currentElement.push(n);
85 | }
86 | });
87 |
88 | if (currentElement.length > 0) {
89 | elements.push({
90 | type: "_CaseDeclElement",
91 | layout: currentElement
92 | });
93 | }
94 |
95 | layout.push({
96 | type: "_CaseDeclElementList",
97 | layout: elements
98 | });
99 | } else if (layout.some(n => n.type == "kw_class")) {
100 | type = "ClassDecl";
101 | } else if (layout.some(n => n.type == "kw_associatedtype")) {
102 | type = "AssociatedtypeDecl";
103 | } else if (layout.some(n => n.type == "pound_if")) {
104 | type = "_IfWithElseConfigDecl";
105 | }
106 | } else if (type === "UnknownStmt") {
107 | if (
108 | (layout[0].type === "kw_if" &&
109 | layout[1].layout[0].layout[0].layout[0].type) === "pound_available"
110 | ) {
111 | type = "IfStmt";
112 |
113 | layout[1].type = "ConditionElementList";
114 | layout[1].layout[0].type = "ConditionElement";
115 | const expr = layout[1].layout[0].layout[0];
116 |
117 | expr.type = "_AvailabilityExpr";
118 | expr.layout.push({
119 | type: "TokenList",
120 | layout: expr.layout.splice(1)
121 | });
122 | }
123 | } else if (type === "UnknownExpr") {
124 | if (layout.length === 1 && layout[0].token) {
125 | const t = layout[0];
126 | ({ token, type, value, text, layout } = t);
127 |
128 | if (t.leadingTrivia) {
129 | leadingTrivia = (leadingTrivia || []).concat(t.leadingTrivia);
130 | }
131 |
132 | if (t.trailingTrivia) {
133 | trailingTrivia = (trailingTrivia || []).concat(t.trailingTrivia);
134 | }
135 | } else if (layout.length === 2 && layout[0].type === "amp_prefix") {
136 | type = "_RefExpr";
137 | } else if (
138 | layout.length === 2 &&
139 | layout[0].type == "l_square" &&
140 | layout[1].type == "r_square"
141 | ) {
142 | type = "ArrayExpr";
143 | layout.splice(1, 0, {
144 | type: "ArrayElementList",
145 | layout: []
146 | });
147 | } else if (
148 | layout.length == 2 &&
149 | layout[0].type === "identifier" &&
150 | layout[1].type === "GenericArgumentClause"
151 | ) {
152 | type = "_GenericTypeExpr";
153 | } else if (
154 | layout.length == 3 &&
155 | (layout[0].type.endsWith("TypeExpr") ||
156 | [
157 | "IdentifierExpr",
158 | "MemberAccessExpr",
159 | "DictionaryExpr",
160 | "ArrayExpr"
161 | ].includes(layout[0].type)) &&
162 | layout[1].type == "period" &&
163 | layout[2].type == "kw_self"
164 | ) {
165 | type = "MemberAccessExpr";
166 | } else if (
167 | layout.length == 3 &&
168 | layout[1].type == "period" &&
169 | layout[2].type == "integer_literal"
170 | ) {
171 | type = "MemberAccessExpr";
172 | } else if (
173 | layout.length == 5 &&
174 | layout[1].type == "period" &&
175 | layout[2].type == "integer_literal" &&
176 | layout[3].type == "period"
177 | ) {
178 | type = "MemberAccessExpr";
179 | layout.unshift({
180 | type: "MemberAccessExpr",
181 | layout: layout.splice(0, 3)
182 | });
183 | } else if (layout.length > 0 && layout[0].type == "pound_selector") {
184 | type = "_SelectorExpr";
185 | }
186 | } else if (type === "UnknownType") {
187 | if (layout.length === 1 && layout[0].type === "kw_class") {
188 | type = "_ClassTypeIdentifier";
189 | }
190 | } else if (type === "Unknown") {
191 | if (layout.some(n => n.type == "pound_elseif")) {
192 | type = "ElseifDirectiveClause";
193 | } else if (layout.some(n => n.type == "pound_else")) {
194 | type = "ElseDirectiveClause";
195 | }
196 | }
197 |
198 | const massageTrivia = trivia => {
199 | if (!trivia || trivia.length === 0) {
200 | return;
201 | }
202 |
203 | trivia.forEach(trivium => {
204 | trivium.type = trivium.type || trivium.kind;
205 | delete trivium.kind;
206 | });
207 |
208 | return trivia;
209 | };
210 |
211 | const result = {
212 | type,
213 | token,
214 | value,
215 | leadingTrivia: massageTrivia(leadingTrivia),
216 | text,
217 | layout,
218 | trailingTrivia: massageTrivia(trailingTrivia)
219 | };
220 |
221 | Object.defineProperty(result, "nodes", {
222 | enumerable: false,
223 | get: function() {
224 | return this.layout;
225 | }
226 | });
227 |
228 | return result;
229 | }
230 |
231 | const findLastLeaf = curr => {
232 | if (
233 | !curr ||
234 | curr.token ||
235 | curr.type == "IdentifierExpr" ||
236 | curr.type.endsWith("LiteralExpr")
237 | ) {
238 | return;
239 | }
240 |
241 | if (
242 | curr.type.startsWith("Unknown") ||
243 | curr.type.endsWith("Stmt") ||
244 | curr.type == "IfConfigDecl"
245 | ) {
246 | return curr;
247 | }
248 |
249 | if (curr.trailingTrivia && curr.trailingTrivia.length > 0) {
250 | return curr;
251 | }
252 |
253 | return (
254 | findLastLeaf(curr.layout && curr.layout[curr.layout.length - 1]) || curr
255 | );
256 | };
257 |
258 | function preferTrailingOverLeadingTrivia(node, path) {
259 | const { type, layout } = node;
260 |
261 | if (!layout || layout.length === 0 || node.type.startsWith("Unknown")) {
262 | return;
263 | }
264 |
265 | layout.forEach(child =>
266 | preferTrailingOverLeadingTrivia(child, [node].concat(path))
267 | );
268 |
269 | const leadingTrivia = (node.leadingTrivia || []).slice();
270 | const trailingTrivia = (node.trailingTrivia || []).slice();
271 |
272 | const elements = [];
273 |
274 | const canMoveUp = () => {
275 | switch (node.type) {
276 | case "StmtList":
277 | case "CodeBlock":
278 | case "CodeBlockItemList":
279 | return path[0].type == "SourceFile";
280 | case "DeclList":
281 | case "SourceFile":
282 | return false;
283 | default:
284 | return true;
285 | }
286 | };
287 |
288 | if (canMoveUp()) {
289 | elements.push({
290 | parent: true,
291 | type: "(" + type + ")",
292 | trailingTrivia: leadingTrivia
293 | });
294 | }
295 |
296 | elements.push(...layout);
297 | elements.push({
298 | type,
299 | leadingTrivia: trailingTrivia
300 | });
301 |
302 | for (let leftIndex = 0; leftIndex < elements.length - 1; leftIndex++) {
303 | const left = elements[leftIndex];
304 | const right = elements[leftIndex + 1];
305 |
306 | if (left.type.startsWith("Unknown") || right.type.startsWith("Unknown")) {
307 | continue;
308 | }
309 |
310 | const rightLeadingTrivia = right.leadingTrivia;
311 |
312 | if (!rightLeadingTrivia || rightLeadingTrivia.length === 0) {
313 | continue;
314 | }
315 |
316 | const target = findLastLeaf(left);
317 |
318 | if (!target) {
319 | continue;
320 | }
321 |
322 | const targetTrailingTrivia = target.trailingTrivia || [];
323 |
324 | loop: for (
325 | let triviumIndex = 0;
326 | triviumIndex < rightLeadingTrivia.length;
327 | triviumIndex++
328 | ) {
329 | const trivium = rightLeadingTrivia[triviumIndex];
330 |
331 | switch (trivium.type) {
332 | case "Newline":
333 | case "Tab":
334 | case "Space":
335 | case "GarbageText":
336 | case "DocBlockComment":
337 | case "DocLineComment":
338 | case "BlockComment":
339 | case "LineComment":
340 | break;
341 | case "Backtick":
342 | break loop;
343 | default:
344 | throw new Error(
345 | "Unexpected trivium: " +
346 | trivium.type +
347 | "\n" +
348 | JSON.stringify(trivium, null, 2)
349 | );
350 | }
351 |
352 | rightLeadingTrivia.splice(triviumIndex--, 1);
353 | targetTrailingTrivia.push(trivium);
354 | }
355 |
356 | if (rightLeadingTrivia.length === 0) {
357 | right.leadingTrivia = undefined;
358 | }
359 |
360 | if (targetTrailingTrivia.length > 0) {
361 | target.trailingTrivia = targetTrailingTrivia;
362 | }
363 | }
364 |
365 | node.leadingTrivia = leadingTrivia.length > 0 ? leadingTrivia : undefined;
366 | node.trailingTrivia = trailingTrivia.length > 0 ? trailingTrivia : undefined;
367 | }
368 |
369 | function extractComments(node, path) {
370 | const processTrivia = (trivia, resultArray, isLeading) => {
371 | if (!trivia) {
372 | return;
373 | }
374 |
375 | let consumeNewline = false;
376 | let onNewLine = trivia.length && trivia[0].__location.startOffset === 0;
377 |
378 | for (let i = 0; i < trivia.length; i++) {
379 | const trivium = trivia[i];
380 | const { type } = trivium;
381 |
382 | switch (type) {
383 | case "Backtick":
384 | case "Tab":
385 | case "Space": {
386 | break;
387 | }
388 | case "Newline": {
389 | if (consumeNewline) {
390 | consumeNewline = false;
391 |
392 | trivium.value--;
393 | trivium.__location.startOffset++;
394 |
395 | if (trivium.value <= 0) {
396 | trivia.splice(i--, 1);
397 | }
398 | } else {
399 | loop: while (i > 0) {
400 | const previous = trivia[i - 1];
401 |
402 | switch (previous.type) {
403 | case "Tab":
404 | case "Space": {
405 | trivia.splice(--i, 1);
406 | break;
407 | }
408 | case "Newline": {
409 | trivium.value += previous.value;
410 | trivia.splice(--i, 1);
411 | break;
412 | }
413 | default: {
414 | break loop;
415 | }
416 | }
417 | }
418 | }
419 |
420 | onNewLine = true;
421 | break;
422 | }
423 | case "GarbageText":
424 | case "DocBlockComment":
425 | case "DocLineComment":
426 | case "BlockComment":
427 | case "LineComment": {
428 | const { __location } = trivium;
429 | let { value } = trivium;
430 |
431 | const isBlockComment = type.endsWith("BlockComment");
432 |
433 | while (i > 0 && ["Space", "Tab"].includes(trivia[i - 1].type)) {
434 | trivia.splice(--i, 1);
435 | }
436 |
437 | const couldRemainTrivia =
438 | onNewLine &&
439 | !node.token &&
440 | path[1].type != "IfStmt" &&
441 | (![
442 | "DeclList",
443 | "StmtList",
444 | "CodeBlock",
445 | "CodeBlockItemList"
446 | ].includes(path[0].type) ||
447 | path[0].layout.length);
448 |
449 | if (isLeading) {
450 | if (couldRemainTrivia) {
451 | onNewLine = false;
452 | consumeNewline = false;
453 | break;
454 | }
455 |
456 | if (i > 0 && trivia[i - 1].type === "Newline") {
457 | const newline = trivia[i - 1];
458 | newline.value--;
459 | if (newline.value <= 0) {
460 | trivia.splice(--i, 1);
461 | } else {
462 | newline.__location.endOffset--;
463 | }
464 | }
465 | } else if (couldRemainTrivia) {
466 | onNewLine = false;
467 | consumeNewline = false;
468 | break;
469 | } else {
470 | consumeNewline = !isBlockComment;
471 | }
472 |
473 | const originalValue = value;
474 |
475 | switch (type) {
476 | case "LineComment":
477 | value = value.slice(2);
478 | break;
479 | case "BlockComment":
480 | value = value.slice(2, value.length - 2);
481 | break;
482 | case "DocLineComment":
483 | value = value.slice(3);
484 | break;
485 | case "DocBlockComment":
486 | value = value.slice(3, value.length - 2);
487 | break;
488 | case "GarbageText":
489 | break;
490 | default:
491 | throw new Error("Unexpected type: " + type);
492 | }
493 |
494 | const comment = {
495 | type: isBlockComment ? "CommentBlock" : "CommentLine",
496 | value,
497 | originalValue
498 | };
499 |
500 | Object.defineProperty(comment, "__location", {
501 | value: __location,
502 | enumerable: Object.getOwnPropertyDescriptor(trivium, "__location")
503 | .enumerable
504 | });
505 |
506 | resultArray.push(comment);
507 | trivia.splice(i--, 1);
508 | onNewLine = false;
509 |
510 | break;
511 | }
512 | default: {
513 | throw new Error("Unexpected type: " + type);
514 | }
515 | }
516 | }
517 |
518 | trivia = trivia.filter(t => t.type != "Space");
519 | return trivia.length > 0 ? trivia : undefined;
520 | };
521 |
522 | const leadingComments = [];
523 | node.leadingTrivia = processTrivia(node.leadingTrivia, leadingComments, true);
524 |
525 | const innerComments = [];
526 | if (node.layout) {
527 | node.layout.forEach(child =>
528 | innerComments.push(...extractComments(child, [child].concat(path)))
529 | );
530 | }
531 |
532 | const trailingComments = [];
533 | node.trailingTrivia = processTrivia(node.trailingTrivia, trailingComments);
534 | return leadingComments.concat(innerComments, trailingComments);
535 | }
536 |
537 | function synthesizeLocation(node, start, text) {
538 | if (!node) {
539 | return start;
540 | } else if (Array.isArray(node)) {
541 | return node.reduce(
542 | (start, node) => synthesizeLocation(node, start, text),
543 | start
544 | );
545 | }
546 |
547 | const outerLocation = { startOffset: start };
548 |
549 | let current = start;
550 |
551 | current = synthesizeLocation(node.leadingTrivia, current, text);
552 |
553 | const innerLocation = { startOffset: current };
554 |
555 | if (node.layout) {
556 | current = synthesizeLocation(node.layout, current, text);
557 | } else if (typeof node.text !== "undefined") {
558 | const s = node.text;
559 | assert.strictEqual(text.slice(current, current + s.length), s);
560 | current += s.length;
561 | } else if (typeof node.value !== "undefined") {
562 | if (Number.isInteger(node.value)) {
563 | current += node.value;
564 | } else {
565 | current += node.value.length;
566 | }
567 | } else if (node.token) {
568 | const s = printToken(node);
569 | assert.strictEqual(text.slice(current, current + s.length), s);
570 | current += s.length;
571 | } else {
572 | throw new Error(
573 | "Don't know how to express " +
574 | JSON.stringify(node.type) +
575 | ":\n" +
576 | JSON.stringify(node, null, 2)
577 | );
578 | }
579 |
580 | innerLocation.endOffset = current;
581 |
582 | current = synthesizeLocation(node.trailingTrivia, current, text);
583 |
584 | outerLocation.endOffset = current;
585 |
586 | const location = node.type.endsWith("List") ? outerLocation : innerLocation;
587 |
588 | Object.defineProperty(node, "__location", {
589 | value: location,
590 | enumerable: false
591 | });
592 |
593 | return current;
594 | }
595 |
596 | function preprocess(text, opts) {
597 | opts.preprocessingCache = {};
598 |
599 | const ast = emitSyntax(text);
600 |
601 | const result = preprocessor.preprocess(ast);
602 |
603 | if (result.bail) {
604 | // eslint-disable-next-line no-console
605 | console.warn("libSyntax had issues parsing this file. Skipping...");
606 |
607 | opts.preprocessingCache = {
608 | ast: {
609 | kind: "GarbageText",
610 | value: text
611 | }
612 | };
613 | } else if (result.modified) {
614 | // eslint-disable-next-line no-console
615 | console.warn(
616 | "libSyntax had issues parsing this file. Re-writing and parsing it again..."
617 | );
618 | text = verbatimPrint(ast);
619 | } else {
620 | opts.preprocessingCache = { ast };
621 | }
622 |
623 | return text;
624 | }
625 |
626 | /** Parses the document */
627 | function parse(text, opts) {
628 | checkVersion();
629 |
630 | let ast;
631 |
632 | // If we are called a second time (i.e. preprocessingCache is already set)
633 | // don't do preprocessing again.
634 | if (opts.preprocessingCache) {
635 | ast = opts.preprocessingCache.ast;
636 | } else {
637 | text = preprocess(text, opts);
638 | ast = opts.preprocessingCache.ast;
639 | }
640 |
641 | delete opts.preprocessingCache;
642 |
643 | if (!ast) {
644 | ast = emitSyntax(text);
645 | }
646 |
647 | ast = massage(ast);
648 | preferTrailingOverLeadingTrivia(ast, []);
649 | const end = synthesizeLocation(ast, 0, text);
650 |
651 | assert.strictEqual(end, text.length);
652 |
653 | ast.comments = extractComments(ast, [ast]);
654 |
655 | return ast;
656 | }
657 |
658 | module.exports = { preprocess, parse };
659 |
--------------------------------------------------------------------------------
/src/parser/preprocessor.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const transferTriviaFromRightToLeft = (left, right) => {
4 | const trailingTrivia = (left.trailingTrivia || []).concat(
5 | right.leadingTrivia || [],
6 | right.trailingTrivia || []
7 | );
8 |
9 | if (trailingTrivia.length > 0) {
10 | left.trailingTrivia = trailingTrivia;
11 | }
12 | };
13 |
14 | const transferTriviaFromLeftToRight = (left, right) => {
15 | const leadingTrivia = (left.leadingTrivia || []).concat(
16 | left.trailingTrivia || [],
17 | right.leadingTrivia || []
18 | );
19 |
20 | if (leadingTrivia.length > 0) {
21 | right.leadingTrivia = leadingTrivia;
22 | }
23 | };
24 |
25 | /**
26 | * Pre-processes a parsed AST to work around limitations of the current libSyntax implementation.
27 | * @param {*} ast
28 | * @returns True, if modifications were necessary.
29 | */
30 | function preprocess(ast) {
31 | const result = { modified: false };
32 |
33 | function visit(node, parent) {
34 | if (!node || !node.layout) {
35 | return;
36 | } else if (!node.kind.startsWith("Unknown")) {
37 | node.layout.filter(n => n).forEach(n => visit(n, node));
38 | return;
39 | }
40 |
41 | const layout = node.layout.filter(n => n.presence === "Present");
42 |
43 | if (
44 | layout.length === 2 &&
45 | layout[1].tokenKind &&
46 | layout[1].tokenKind.kind === "semi"
47 | ) {
48 | const canStrip =
49 | parent.layout.filter(n => n.presence === "Present").length === 1;
50 |
51 | // eslint-disable-next-line no-console
52 | console.warn(
53 | "Found semicolon that confused libSyntax. " +
54 | (canStrip ? "Stripping" : "Breaking") +
55 | "..."
56 | );
57 |
58 | if (!canStrip) {
59 | (layout[1].leadingTrivia || (layout[1].leadingTrivia = [])).push({
60 | kind: "Newline",
61 | value: 1
62 | });
63 | }
64 |
65 | transferTriviaFromRightToLeft(layout[0], layout[1]);
66 |
67 | // Clear out current node
68 | Object.keys(node)
69 | .filter(k => k.indexOf("Trivia") < 0)
70 | .forEach(k => {
71 | delete node[k];
72 | });
73 |
74 | Object.assign(node, layout[0]);
75 | result.modified = true;
76 | } else if (
77 | layout.length === 3 &&
78 | layout[0].tokenKind &&
79 | layout[0].tokenKind.kind === "l_paren" &&
80 | parent.kind !== "UnknownDecl"
81 | ) {
82 | const parameters = layout[1].layout;
83 |
84 | const canStrip = parameters.every(
85 | n =>
86 | !n.layout ||
87 | n.layout.every(
88 | n => !n || !n.tokenKind || n.tokenKind.kind !== "colon"
89 | )
90 | );
91 |
92 | // eslint-disable-next-line no-console
93 | console.warn(
94 | "Found closure with " +
95 | (canStrip ? "optional" : "required") +
96 | " parentheses that confused libSyntax. " +
97 | (canStrip ? "Stripping" : "Bailing") +
98 | "..."
99 | );
100 |
101 | if (canStrip) {
102 | transferTriviaFromLeftToRight(layout[0], layout[1]);
103 | transferTriviaFromRightToLeft(layout[1], layout[2]);
104 | node.layout = [layout[1]];
105 | result.modified = true;
106 | } else {
107 | result.bail = true;
108 | }
109 | }
110 |
111 | node.layout.forEach(c => visit(c, node));
112 | }
113 |
114 | visit(ast);
115 | return result;
116 | }
117 |
118 | module.exports = { preprocess };
119 |
--------------------------------------------------------------------------------
/src/parser/wrapper.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const spawnSync = require("child_process").spawnSync;
4 |
5 | function getCommand() {
6 | return process.env.PRETTIER_SWIFT_SWIFTC || process.env.SWIFTC || "swiftc";
7 | }
8 |
9 | function checkVersion() {
10 | const result = spawnSync(getCommand(), ["--version"]);
11 |
12 | if (result.error || result.status) {
13 | throw new Error(result.error || result.stderr.toString());
14 | }
15 |
16 | const stdout = result.stdout.toString();
17 | const match = /Swift version ([0-9]+\.[0-9]+(\.[0-9]+)?)/.exec(stdout);
18 |
19 | if (!match) {
20 | // eslint-disable-next-line no-console
21 | console.error("Could not detect Swift version:", stdout);
22 | throw new Error("Unsupported Swift version (required: >4.1): " + stdout);
23 | }
24 |
25 | const components = match[1].split(".");
26 |
27 | if (components[0] === "4") {
28 | if (components[1] < 2) {
29 | throw new Error("Unsupported Swift version. Required: 4.2");
30 | } else {
31 | return;
32 | }
33 | } else if (components[0] < 4) {
34 | throw new Error("Unsupported Swift version. Required: 4.2");
35 | }
36 |
37 | // eslint-disable-next-line no-console
38 | console.error("Potentially unsupported Swift version. Use Swift 4.2");
39 | }
40 |
41 | function emitSyntax(text) {
42 | const result = spawnSync(getCommand(), ["-frontend", "-emit-syntax", "-"], {
43 | input: text,
44 | timeout: 60000
45 | });
46 |
47 | if (result.error || result.status) {
48 | throw new Error(result.error || result.stderr.toString());
49 | }
50 |
51 | return JSON.parse(result.stdout.toString());
52 | }
53 |
54 | module.exports = {
55 | emitSyntax,
56 | checkVersion
57 | };
58 |
--------------------------------------------------------------------------------
/src/printer/builders.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const doc = require("prettier").doc;
4 | const docBuilders = doc.builders;
5 |
6 | const { join, hardline, softline, line } = docBuilders;
7 |
8 | function smartJoin(separator, parts) {
9 | const result = [];
10 | let lastPart;
11 |
12 | parts.filter(x => x).forEach((part, index) => {
13 | const firstPart = part.parts ? part.parts[0] : part;
14 | if (
15 | index > 0 &&
16 | firstPart !== ":" &&
17 | firstPart !== "..." &&
18 | firstPart !== ")" &&
19 | firstPart !== "<" &&
20 | lastPart !== "("
21 | ) {
22 | result.push(separator);
23 | }
24 |
25 | lastPart = part;
26 | result.push(part);
27 | });
28 |
29 | return concat(result);
30 | }
31 |
32 | function concat(parts) {
33 | parts = parts.filter(x => x);
34 |
35 | switch (parts.length) {
36 | case 0:
37 | return "";
38 | case 1:
39 | return parts[0];
40 | default:
41 | return docBuilders.concat(parts);
42 | }
43 | }
44 |
45 | module.exports = {
46 | smartJoin,
47 | concat,
48 | join,
49 | hardline,
50 | softline,
51 | line
52 | };
53 |
--------------------------------------------------------------------------------
/src/printer/chain.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const util = require("prettier/src/common/util");
4 | const comments = require("prettier/src/main/comments");
5 | const doc = require("prettier").doc;
6 | const {
7 | indent,
8 | hardline,
9 | group,
10 | breakParent,
11 | join,
12 | conditionalGroup
13 | } = doc.builders;
14 | const { willBreak } = doc.utils;
15 |
16 | const { concat } = require("./builders");
17 |
18 | // We detect calls on member expressions specially to format a
19 | // common pattern better. The pattern we are looking for is this:
20 | //
21 | // arr
22 | // .map(x => x + 1)
23 | // .filter(x => x > 10)
24 | // .some(x => x % 2)
25 | //
26 | // The way it is structured in the AST is via a nested sequence of
27 | // MemberAccessExpr and FunctionCallExpr. We need to traverse the AST
28 | // and make groups out of it to print it in the desired way.
29 | function printMemberChain(path, options, print) {
30 | // The first phase is to linearize the AST by traversing it down.
31 | //
32 | // a().b()
33 | // has the following AST structure:
34 | // FunctionCallExpr(MemberAccessExpr(FunctionCallExpr(IdentifierExpr)))
35 | // and we transform it into
36 | // [IdentifierExpr, FunctionCallExpr, MemberAccessExpr, FunctionCallExpr]
37 | const printedNodes = [];
38 |
39 | // Here we try to retain one typed empty line after each call expression or
40 | // the first group whether it is in parentheses or not
41 | function shouldInsertEmptyLineAfter(node) {
42 | const originalText = options.originalText;
43 | const nextCharIndex = util.getNextNonSpaceNonCommentCharacterIndex(
44 | originalText,
45 | node,
46 | options.locEnd
47 | );
48 | const nextChar = originalText.charAt(nextCharIndex);
49 |
50 | // if it is cut off by a parenthesis, we only account for one typed empty
51 | // line after that parenthesis
52 | if (nextChar == ")") {
53 | return util.isNextLineEmptyAfterIndex(originalText, nextCharIndex + 1);
54 | }
55 |
56 | return util.isNextLineEmpty(originalText, node, options.locEnd);
57 | }
58 |
59 | function rec(path) {
60 | const node = path.getValue();
61 | if (
62 | node.type === "FunctionCallExpr" &&
63 | (isMemberish(node.layout[0]) ||
64 | node.layout[0].type === "FunctionCallExpr")
65 | ) {
66 | printedNodes.unshift({
67 | node: node,
68 | printed: concat([
69 | comments.printComments(
70 | path,
71 | () =>
72 | concat([
73 | printOptionalToken(path),
74 | printFunctionTypeParameters(path, options, print),
75 | printArgumentsList(path, options, print)
76 | ]),
77 | options
78 | ),
79 | shouldInsertEmptyLineAfter(node) ? hardline : ""
80 | ])
81 | });
82 |
83 | Object.defineProperty(node, "callee", {
84 | enumerable: false,
85 | value: node.layout[0]
86 | });
87 |
88 | path.call(callee => rec(callee), "callee");
89 | } else if (isMemberish(node)) {
90 | printedNodes.unshift({
91 | node: node,
92 | printed: comments.printComments(
93 | path,
94 | () =>
95 | node.type === "MemberAccessExpr"
96 | ? printMemberLookup(path, options, print)
97 | : printBindExpressionCallee(path, options, print),
98 | options
99 | )
100 | });
101 |
102 | Object.defineProperty(node, "object", {
103 | enumerable: false,
104 | value: node.layout[0]
105 | });
106 |
107 | path.call(object => rec(object), "object");
108 | } else {
109 | printedNodes.unshift({
110 | node: node,
111 | printed: path.call(print)
112 | });
113 | }
114 | }
115 | // Note: the comments of the root node have already been printed, so we
116 | // need to extract this first call without printing them as they would
117 | // if handled inside of the recursive call.
118 | const node = path.getValue();
119 | printedNodes.unshift({
120 | node,
121 | printed: concat([
122 | printOptionalToken(path),
123 | printFunctionTypeParameters(path, options, print),
124 | printArgumentsList(path, options, print)
125 | ])
126 | });
127 | path.call(callee => rec(callee), "callee");
128 |
129 | // Once we have a linear list of printed nodes, we want to create groups out
130 | // of it.
131 | //
132 | // a().b.c().d().e
133 | // will be grouped as
134 | // [
135 | // [Identifier, FunctionCallExpr],
136 | // [MemberAccessExpr, MemberAccessExpr, FunctionCallExpr],
137 | // [MemberAccessExpr, FunctionCallExpr],
138 | // [MemberAccessExpr],
139 | // ]
140 | // so that we can print it as
141 | // a()
142 | // .b.c()
143 | // .d()
144 | // .e
145 |
146 | // The first group is the first node followed by
147 | // - as many FunctionCallExpr as possible
148 | // < fn()()() >.something()
149 | // - as many array acessors as possible
150 | // < fn()[0][1][2] >.something()
151 | // - then, as many MemberAccessExpr as possible but the last one
152 | // < this.items >.something()
153 | const groups = [];
154 | let currentGroup = [printedNodes[0]];
155 | let i = 1;
156 | for (; i < printedNodes.length; ++i) {
157 | if (
158 | printedNodes[i].node.type === "FunctionCallExpr" ||
159 | (printedNodes[i].node.type === "MemberAccessExpr" &&
160 | printedNodes[i].node.computed &&
161 | isNumericLiteral(printedNodes[i].node.property))
162 | ) {
163 | currentGroup.push(printedNodes[i]);
164 | } else {
165 | break;
166 | }
167 | }
168 | if (printedNodes[0].node.type !== "FunctionCallExpr") {
169 | for (; i + 1 < printedNodes.length; ++i) {
170 | if (
171 | isMemberish(printedNodes[i].node) &&
172 | isMemberish(printedNodes[i + 1].node)
173 | ) {
174 | currentGroup.push(printedNodes[i]);
175 | } else {
176 | break;
177 | }
178 | }
179 | }
180 | groups.push(currentGroup);
181 | currentGroup = [];
182 |
183 | // Then, each following group is a sequence of MemberAccessExpr followed by
184 | // a sequence of FunctionCallExpr. To compute it, we keep adding things to the
185 | // group until we has seen a FunctionCallExpr in the past and reach a
186 | // MemberAccessExpr
187 | let hasSeenFunctionCallExpr = false;
188 | for (; i < printedNodes.length; ++i) {
189 | if (hasSeenFunctionCallExpr && isMemberish(printedNodes[i].node)) {
190 | // [0] should be appended at the end of the group instead of the
191 | // beginning of the next one
192 | if (
193 | printedNodes[i].node.computed &&
194 | isNumericLiteral(printedNodes[i].node.property)
195 | ) {
196 | currentGroup.push(printedNodes[i]);
197 | continue;
198 | }
199 |
200 | groups.push(currentGroup);
201 | currentGroup = [];
202 | hasSeenFunctionCallExpr = false;
203 | }
204 |
205 | if (printedNodes[i].node.type === "FunctionCallExpr") {
206 | hasSeenFunctionCallExpr = true;
207 | }
208 | currentGroup.push(printedNodes[i]);
209 |
210 | if (
211 | printedNodes[i].node.comments &&
212 | printedNodes[i].node.comments.some(comment => comment.trailing)
213 | ) {
214 | groups.push(currentGroup);
215 | currentGroup = [];
216 | hasSeenFunctionCallExpr = false;
217 | }
218 | }
219 | if (currentGroup.length > 0) {
220 | groups.push(currentGroup);
221 | }
222 |
223 | // There are cases like Object.keys(), Observable.of(), _.values() where
224 | // they are the subject of all the chained calls and therefore should
225 | // be kept on the same line:
226 | //
227 | // Object.keys(items)
228 | // .filter(x => x)
229 | // .map(x => x)
230 | //
231 | // In order to detect those cases, we use an heuristic: if the first
232 | // node is just an identifier with the name starting with a capital
233 | // letter, just a sequence of _$ or this. The rationale is that they are
234 | // likely to be factories.
235 | function isFactory(node) {
236 | return (
237 | node.type === "kw_self" ||
238 | (node.text && node.text.match(/(^[A-Z])|^[_$]+$/))
239 | );
240 | }
241 |
242 | const shouldMerge =
243 | groups.length >= 2 &&
244 | !groups[1][0].node.comments &&
245 | ((groups[0].length === 1 &&
246 | (groups[0][0].node.type === "kw_self" ||
247 | groups[0][0].node.type.endsWith("TypeExpr") ||
248 | groups[0][0].node.type.endsWith("SpecializeExpr") ||
249 | (groups[0][0].node.type === "IdentifierExpr" &&
250 | (isFactory(groups[0][0].node.layout[0]) ||
251 | (groups[1].length && groups[1][0].node.computed))))) ||
252 | (groups[0].length > 1 &&
253 | groups[0][groups[0].length - 1].node.type === "MemberAccessExpr" &&
254 | groups[0][groups[0].length - 1].node.layout[2].type === "identifier" &&
255 | (isFactory(groups[0][groups[0].length - 1].node.layout[2]) ||
256 | (groups[1].length && groups[1][0].node.computed))));
257 |
258 | function printGroup(printedGroup) {
259 | return concat(printedGroup.map(tuple => tuple.printed));
260 | }
261 |
262 | function printIndentedGroup(groups) {
263 | if (groups.length === 0) {
264 | return "";
265 | }
266 | return indent(
267 | group(concat([hardline, join(hardline, groups.map(printGroup))]))
268 | );
269 | }
270 |
271 | const printedGroups = groups.map(printGroup);
272 | const oneLine = concat(printedGroups);
273 |
274 | const cutoff = shouldMerge ? 3 : 2;
275 | const flatGroups = groups
276 | .slice(0, cutoff)
277 | .reduce((res, group) => res.concat(group), []);
278 |
279 | const hasComment =
280 | flatGroups.slice(1, -1).some(node => hasLeadingComment(node.node)) ||
281 | flatGroups.slice(0, -1).some(node => hasTrailingComment(node.node)) ||
282 | (groups[cutoff] && hasLeadingComment(groups[cutoff][0].node));
283 |
284 | // If we only have a single `.`, we shouldn't do anything fancy and just
285 | // render everything concatenated together.
286 | if (groups.length <= cutoff && !hasComment) {
287 | return group(concat(printedGroups));
288 | }
289 |
290 | // Find out the last node in the first group and check if it has an
291 | // empty line after
292 | const lastNodeBeforeIndent = util.getLast(
293 | shouldMerge ? groups.slice(1, 2)[0] : groups[0]
294 | ).node;
295 | const shouldHaveEmptyLineBeforeIndent =
296 | lastNodeBeforeIndent.type !== "FunctionCallExpr" &&
297 | shouldInsertEmptyLineAfter(lastNodeBeforeIndent);
298 |
299 | const expanded = concat([
300 | printGroup(groups[0]),
301 | shouldMerge ? concat(groups.slice(1, 2).map(printGroup)) : "",
302 | shouldHaveEmptyLineBeforeIndent ? hardline : "",
303 | printIndentedGroup(groups.slice(shouldMerge ? 2 : 1))
304 | ]);
305 |
306 | const functionCallExprCount = printedNodes.filter(
307 | tuple => tuple.node.type === "FunctionCallExpr"
308 | ).length;
309 |
310 | // We don't want to print in one line if there's:
311 | // * A comment.
312 | // * 3 or more chained calls.
313 | // * Any group but the last one has a hard line.
314 | // If the last group is a function it's okay to inline if it fits.
315 | if (
316 | hasComment ||
317 | functionCallExprCount >= 3 ||
318 | printedGroups.slice(0, -1).some(willBreak)
319 | ) {
320 | return group(expanded);
321 | }
322 |
323 | return concat([
324 | // We only need to check `oneLine` because if `expanded` is chosen
325 | // that means that the parent group has already been broken
326 | // naturally
327 | willBreak(oneLine) || shouldHaveEmptyLineBeforeIndent ? breakParent : "",
328 | conditionalGroup([oneLine, expanded])
329 | ]);
330 | }
331 |
332 | function isNumericLiteral(node) {
333 | return node.type === "IntegerLiteralExpr";
334 | }
335 |
336 | function isMemberish(node) {
337 | return node.type === "MemberAccessExpr" || node.type === "ImplicitMemberExpr";
338 | }
339 |
340 | function printOptionalToken() {
341 | return "";
342 | }
343 |
344 | function printFunctionTypeParameters() {
345 | return "";
346 | }
347 |
348 | function printBindExpressionCallee(path) {
349 | const part = path.getValue().layout.find(l => l.type == "identifier");
350 | return part.text;
351 | }
352 |
353 | function printArgumentsList(path, options, print) {
354 | return require("./generic").genericPrint(
355 | path,
356 | Object.assign({}, options, { argumentsOnly: true }),
357 | print
358 | );
359 | }
360 |
361 | function printMemberLookup(path, options, print) {
362 | const n = path.getValue();
363 | n.memberLookup = n.layout.slice(1);
364 | return concat(path.map(print, "memberLookup"));
365 | }
366 |
367 | function hasLeadingComment(node) {
368 | return node.comments && node.comments.some(comment => comment.leading);
369 | }
370 |
371 | function hasTrailingComment(node) {
372 | return node.comments && node.comments.some(comment => comment.trailing);
373 | }
374 |
375 | module.exports = {
376 | printMemberChain,
377 | isMemberish
378 | };
379 |
--------------------------------------------------------------------------------
/src/printer/generic.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const assert = require("assert");
4 |
5 | const { mapDoc } = require("prettier/src/common/util");
6 | const comments = require("prettier/src/main/comments");
7 |
8 | const doc = require("prettier").doc;
9 | const docBuilders = doc.builders;
10 |
11 | const { printToken } = require("./tokens");
12 | const { verbatimPrint } = require("./verbatim");
13 | const chain = require("./chain");
14 | const isMemberish = chain.isMemberish;
15 | const printMemberChain = chain.printMemberChain;
16 |
17 | const identity = o => o;
18 |
19 | const {
20 | align,
21 | indent,
22 | line,
23 | hardline,
24 | softline,
25 | group,
26 | breakParent,
27 | join,
28 | ifBreak
29 | } = docBuilders;
30 |
31 | const { smartJoin, concat } = require("./builders");
32 |
33 | function printList(path, print) {
34 | return concat([
35 | softline,
36 | group(smartJoin(concat([",", line]), path.map(print, "layout")))
37 | ]);
38 | }
39 |
40 | function printWithoutNewlines(doc) {
41 | return mapDoc(doc, doc => {
42 | if (doc === line) {
43 | return " ";
44 | } else if (doc === softline) {
45 | return "";
46 | }
47 |
48 | return doc;
49 | });
50 | }
51 |
52 | function genericPrint(path, options, print) {
53 | const n = path.getValue();
54 |
55 | if (typeof n === "string") {
56 | return n;
57 | }
58 |
59 | const { type } = n;
60 |
61 | if (!type) {
62 | throw new Error("Node without type: " + JSON.stringify(n, null, 2));
63 | }
64 |
65 | const parentType = path.getParentNode() ? path.getParentNode().type : "";
66 |
67 | if (
68 | type === "r_paren" &&
69 | parentType.startsWith("_") &&
70 | parentType.endsWith("Decl")
71 | ) {
72 | return ") ";
73 | } else if (n.token) {
74 | return printToken(n);
75 | }
76 |
77 | switch (type) {
78 | case "SourceFile": {
79 | const parts = path.map(print, "layout");
80 |
81 | // Only force a trailing newline if there were any contents.
82 | if (n.layout.length || n.comments) {
83 | parts.push(hardline);
84 | }
85 |
86 | parts.unshift(
87 | concat([comments.printDanglingComments(path, options, true)])
88 | );
89 |
90 | return concat(parts);
91 | }
92 | case "DeclList":
93 | case "CodeBlockItemList": {
94 | if (n.layout.length === 0) {
95 | return " ";
96 | }
97 |
98 | const isInsideClosureExpression = parentType === "ClosureExpr";
99 | const isInsideGuardStatement =
100 | (path.getParentNode(1) || {}).type === "GuardStmt";
101 | const isInsideDeferStatement =
102 | (path.getParentNode(1) || {}).type === "DeferStmt";
103 |
104 | const shouldBreak =
105 | !isInsideGuardStatement &&
106 | !isInsideDeferStatement &&
107 | !isInsideClosureExpression;
108 |
109 | return concat([
110 | shouldBreak ? breakParent : "",
111 | join(hardline, path.map(print, "layout"))
112 | ]);
113 | }
114 | case "_EnumDeclBlock":
115 | case "AccessorBlock":
116 | case "MemberDeclBlock":
117 | case "CodeBlock": {
118 | const body = path.map(print, "layout");
119 | const first = body.shift();
120 | const last = body.pop();
121 |
122 | // Special case: empty block
123 | if (!n.layout[1].layout.length) {
124 | return concat([first, " ", last]);
125 | }
126 |
127 | return group(
128 | concat([indent(concat([first, line, ...body])), line, last])
129 | );
130 | }
131 | case "TuplePatternElementList":
132 | case "GenericRequirementList": {
133 | if (!n.layout.length) {
134 | return "";
135 | }
136 |
137 | return group(indent(printList(path, print)));
138 | }
139 | case "AccessorList": {
140 | return join(line, path.map(print, "layout"));
141 | }
142 | case "SwitchCaseList": {
143 | return concat([
144 | hardline,
145 | smartJoin(hardline, path.map(print, "layout")),
146 | hardline
147 | ]);
148 | }
149 | case "StmtList": {
150 | const children = path.map(print, "layout");
151 |
152 | if (!children.length) {
153 | if (n.comments) {
154 | return concat([
155 | comments.printDanglingComments(
156 | path,
157 | options,
158 | /* sameIndent */ parentType === "SourceFile"
159 | ),
160 | hardline
161 | ]);
162 | }
163 |
164 | return "";
165 | }
166 |
167 | if (parentType === "_CaseBlock") {
168 | return indent(
169 | concat([breakParent, softline, join(hardline, children)])
170 | );
171 | } else if (
172 | parentType === "SourceFile" ||
173 | parentType.match(/DirectiveClause/) ||
174 | parentType.match(/ConfigDecl/)
175 | ) {
176 | return join(hardline, children);
177 | }
178 |
179 | let forceBreak = children.length > 1;
180 |
181 | if (
182 | parentType === "ClosureExpr" &&
183 | path.getParentNode(1).type === "FunctionCallExpr" &&
184 | path.getParentNode(5).type === "VariableDecl" &&
185 | path
186 | .getParentNode(5)
187 | .layout.some(
188 | c =>
189 | c.type === "ModifierList" &&
190 | c.layout.some(c => c.layout.some(c => c.text === "lazy"))
191 | )
192 | ) {
193 | forceBreak = true;
194 | }
195 |
196 | return concat([
197 | indent(concat([softline, join(hardline, children)])),
198 | forceBreak ? breakParent : "",
199 | line
200 | ]);
201 | }
202 | case "ClosureParamList": {
203 | // never break for single parameters or _, _, _,
204 | if (
205 | n.layout.length < 2 ||
206 | n.layout.every(param => param.type === "kw__")
207 | ) {
208 | return concat(path.map(print, "layout"));
209 | }
210 |
211 | return group(indent(printList(path, print)));
212 | }
213 | case "_CaseDeclElementList":
214 | case "CaseItemList":
215 | case "ConditionElementList":
216 | case "InheritedTypeList":
217 | case "PatternBindingList": {
218 | if (!n.layout.length) {
219 | return "";
220 | } else if (n.layout.length === 1) {
221 | const maybeIndent =
222 | n.type == "ConditionElementList" ? indent : identity;
223 |
224 | return group(
225 | concat([
226 | maybeIndent(concat(path.map(print, "layout"))),
227 | parentType === "GuardStmt" ? " " : ""
228 | ])
229 | );
230 | } else if (path.getParentNode(1).type === "SwitchCase") {
231 | return group(
232 | indent(join(concat([",", line]), path.map(print, "layout")))
233 | );
234 | }
235 |
236 | return group(
237 | concat([
238 | indent(printList(path, print)),
239 | parentType === "GuardStmt" ? line : softline
240 | ])
241 | );
242 | }
243 | // Lists that are already surrounded by characters (parens, braces...)
244 | // where indenting is handled by the parent node.
245 | case "FunctionCallArgumentList":
246 | case "GenericParameterList":
247 | case "GenericArgumentList":
248 | case "TupleElementList":
249 | case "TupleTypeElementList":
250 | case "FunctionParameterList":
251 | case "ClosureCaptureItemList": {
252 | if (!n.layout.length) {
253 | return "";
254 | }
255 |
256 | return smartJoin(concat([",", line]), path.map(print, "layout"));
257 | }
258 | case "ArrayElementList":
259 | case "DictionaryElementList": {
260 | if (!n.layout.length) {
261 | return "";
262 | } else if (n.type === "ArrayElementList" && n.layout.length === 1) {
263 | return concat(path.map(print, "layout"));
264 | }
265 |
266 | return concat([
267 | smartJoin(concat([",", line]), path.map(print, "layout")),
268 | options.trailingComma === "all" ? ifBreak(",", "") : ""
269 | ]);
270 | }
271 | case "SubscriptDecl": {
272 | const body = path.map(print, "layout");
273 | const first = body.shift();
274 | return concat([first, join(" ", body)]);
275 | }
276 | case "InitializerDecl":
277 | case "DeinitializerDecl":
278 | case "TypealiasDecl":
279 | case "VariableDecl":
280 | case "FunctionDecl":
281 | case "AccessorDecl":
282 | case "ProtocolDecl":
283 | case "StructDecl":
284 | case "ImportDecl":
285 | case "ExtensionDecl":
286 | case "ClassDecl": {
287 | const body = n.layout.slice();
288 | let prefix;
289 |
290 | if (body[0].type === "AttributeList" || body[0].type === "ModifierList") {
291 | prefix = body.shift();
292 | }
293 |
294 | const index = body.findIndex(n => {
295 | return (
296 | [
297 | "identifier",
298 | "contextual_keyword",
299 | "kw_subscript",
300 | "kw_init",
301 | "kw_deinit",
302 | "kw_var",
303 | "kw_let",
304 | "kw_import"
305 | ].includes(n.type) ||
306 | n.type.endsWith("Identifier") ||
307 | n.type.startsWith("oper_")
308 | );
309 | });
310 |
311 | if (index < 0) {
312 | throw new Error(
313 | "No identifier found: " + body.map(c => c.type).join(", ")
314 | );
315 | }
316 |
317 | const start = body.splice(0, index);
318 | const middle = [body.shift()];
319 |
320 | if (middle[0].type.startsWith("oper_")) {
321 | middle.push(" "); // add spacing after operators
322 | }
323 |
324 | while (
325 | body[0] &&
326 | [
327 | "GenericParameterClause",
328 | "AccessorParameter",
329 | "FunctionSignature",
330 | // For InitializerDecl:
331 | "ParameterClause",
332 | "question_postfix",
333 | "question_infix" // if developer inserted an accidental space
334 | ].includes(body[0].type)
335 | ) {
336 | middle.push(body.shift());
337 | }
338 |
339 | const last = body.pop();
340 |
341 | Object.assign(n, {
342 | prefix,
343 | start,
344 | middle,
345 | body,
346 | last
347 | });
348 |
349 | return concat([
350 | prefix ? path.call(print, "prefix") : "",
351 | group(
352 | smartJoin(" ", [
353 | ...path.map(print, "start"),
354 | concat(path.map(print, "middle")),
355 | ...path.map(print, "body")
356 | ])
357 | ),
358 | last ? concat([" ", path.call(print, "last")]) : ""
359 | ]);
360 | }
361 | case "_EnumDecl":
362 | case "_ExtensionDecl": {
363 | const index = n.layout.findIndex(n => n.type == "l_brace");
364 | const result = path.map(print, "layout");
365 | const start = result.slice(0, index);
366 | const end = result.slice(index);
367 | return concat([smartJoin(" ", start), " ", ...end]);
368 | }
369 | case "GuardStmt": {
370 | const body = path.map(print, "layout");
371 | const index = n.layout.findIndex(n => n.type == "kw_else");
372 | const start = body.slice(0, index);
373 | const end = body.slice(index);
374 | return group(concat([smartJoin(" ", start), group(smartJoin(" ", end))]));
375 | }
376 | case "ReturnStmt": {
377 | const result = smartJoin(" ", path.map(print, "layout"));
378 |
379 | return concat([
380 | path.getParentNode().layout[0] === n &&
381 | path.getParentNode(3).type === "GuardStmt"
382 | ? ""
383 | : breakParent,
384 | result
385 | ]);
386 | }
387 | case "SwitchCase": {
388 | return group(indent(join(line, path.map(print, "layout"))));
389 | }
390 | case "SwitchStmt": {
391 | const body = path.map(print, "layout");
392 | const first = body.shift();
393 | const variable = body.shift();
394 | const last = body.pop();
395 | return concat([first, " ", variable, " ", concat(body), last]);
396 | }
397 | case "ThrowStmt": {
398 | return concat([breakParent, smartJoin(" ", path.map(print, "layout"))]);
399 | }
400 | case "CompositionType":
401 | case "FallthroughStmt":
402 | case "IfStmt":
403 | case "AssociatedtypeDecl": // decls
404 | case "TypeAnnotation": // annotations
405 | case "OptionalBindingCondition": // conditions
406 | case "MatchingPatternCondition":
407 | case "CompositionTypeElementList": // lists
408 | case "ForInStmt": // statements
409 | case "WhileStmt":
410 | case "RepeatWhileStmt":
411 | case "BreakStmt":
412 | case "ContinueStmt":
413 | case "DoStmt":
414 | case "DeclarationStmt":
415 | case "ExpressionStmt": {
416 | return smartJoin(" ", path.map(print, "layout"));
417 | }
418 | case "ModifierList": {
419 | n.body = n.layout.slice();
420 |
421 | if (n.body[0].type === "AttributeList") {
422 | n.attributes = n.body.shift();
423 | }
424 |
425 | return concat([
426 | n.attributes ? path.call(print, "attributes") : "",
427 | join(" ", path.map(print, "body")),
428 | n.body.length ? " " : ""
429 | ]);
430 | }
431 | case "AttributeList": {
432 | if (n.layout.length === 0) {
433 | return "";
434 | } else if (
435 | !parentType.endsWith("Decl") &&
436 | !path.getParentNode(1).type.endsWith("Decl")
437 | ) {
438 | return join(" ", path.map(print, "layout"));
439 | }
440 |
441 | const inline = n.layout.every(
442 | c =>
443 | ["IBOutlet", "IBAction", "objc", "testable"].includes(
444 | c.layout[1].text
445 | ) && !(c.layout[2] && c.layout[2].layout.length)
446 | );
447 |
448 | const breaker = inline ? line : hardline;
449 |
450 | return group(concat([join(breaker, path.map(print, "layout")), breaker]));
451 | }
452 | case "TypeInitializerClause":
453 | case "InitializerClause": {
454 | n.op = n.layout[0];
455 | n.end = n.layout.slice(1);
456 |
457 | return concat([
458 | parentType == "PatternBinding" ? " " : "",
459 | path.call(print, "op"),
460 | " ",
461 | group(...path.map(print, "end"))
462 | ]);
463 | }
464 | case "TryExpr": {
465 | const body = path.map(print, "layout");
466 | const last = body.pop();
467 | return smartJoin(" ", [concat(body), last]);
468 | }
469 | case "IsExpr":
470 | case "AsExpr": {
471 | const body = path.map(print, "layout");
472 | const last = body.pop();
473 |
474 | const maybeIndent = doc =>
475 | parentType === "ExprList" ? doc : indent(doc);
476 |
477 | return group(maybeIndent(concat([line, ...body, " ", last])));
478 | }
479 | case "WhereClause":
480 | case "GenericWhereClause": {
481 | const body = n.layout.slice();
482 | n.keyword = body.shift();
483 | n.body = body;
484 | return group(
485 | indent(
486 | concat([
487 | softline,
488 | path.call(print, "keyword"),
489 | " ",
490 | join(" ", path.map(print, "body"))
491 | ])
492 | )
493 | );
494 | }
495 | case "ExprList": {
496 | if (
497 | n.layout.length === 3 &&
498 | n.layout[1].type === "AssignmentExpr" &&
499 | ([
500 | "ArrayExpr",
501 | "DictionaryExpr",
502 | "FunctionCallExpr",
503 | "ClosureExpr"
504 | ].includes(n.layout[2].type) ||
505 | n.layout[2].type.endsWith("LiteralExpr"))
506 | ) {
507 | return group(concat(path.map(print, "layout")));
508 | }
509 |
510 | return group(indent(concat(path.map(print, "layout"))));
511 | }
512 | case "StringInterpolationExpr": {
513 | return printWithoutNewlines(concat(path.map(print, "layout")));
514 | }
515 | case "CatchClauseList": {
516 | return join(" ", path.map(print, "layout"));
517 | }
518 | case "ElseDirectiveClause":
519 | case "ElseifDirectiveClause":
520 | case "_IfWithElseConfigDecl":
521 | case "IfConfigDecl": {
522 | const hasCondition = type != "ElseDirectiveClause";
523 | const body = n.layout.slice();
524 |
525 | n.keyword = body.shift();
526 | n.condition = hasCondition ? body.shift() : undefined;
527 | n.code = body.shift();
528 | n.tail = body;
529 |
530 | const condition =
531 | hasCondition && printWithoutNewlines(path.call(print, "condition"));
532 |
533 | return concat([
534 | path.call(print, "keyword"),
535 | hasCondition ? concat([" ", condition]) : "",
536 | join(hardline, [
537 | indent(concat([hardline, path.call(print, "code")])),
538 | ...path.map(print, "tail")
539 | ])
540 | ]);
541 | }
542 | case "DictionaryType": {
543 | const body = path.map(print, "layout");
544 | assert.strictEqual(body.length, 5);
545 | const left = body.slice(0, 3);
546 | const right = body.slice(3);
547 | return join(" ", [concat(left), concat(right)]);
548 | }
549 | case "PatternBinding": {
550 | const body = path.map(print, "layout");
551 |
552 | // Explicit insertion of space for accessor blocks:
553 | // `var name: String_HERE_{ return "123" }`
554 | if (n.layout[n.layout.length - 1].type === "AccessorBlock") {
555 | const rest = body.pop();
556 | return concat([...body, " ", rest]);
557 | }
558 |
559 | return concat(path.map(print, "layout"));
560 | }
561 | case "TokenList": {
562 | const printedTokens = path.map(print, "layout");
563 | const elements = [];
564 | let currentElement = [];
565 |
566 | const leftParen = printedTokens.shift();
567 | const rightParen = printedTokens.pop();
568 |
569 | printedTokens.forEach(t => {
570 | if (t === ",") {
571 | elements.push(currentElement);
572 | currentElement = [];
573 | } else {
574 | currentElement.push(t);
575 | }
576 | });
577 |
578 | if (currentElement.length > 0) {
579 | elements.push(currentElement);
580 | }
581 |
582 | return concat([
583 | leftParen,
584 | join(", ", elements.map(e => join(" ", e))),
585 | rightParen
586 | ]);
587 | }
588 | case "_CaseDecl": {
589 | const body = path.map(print, "layout");
590 | const keyword = body.shift();
591 | return concat([keyword, " ", ...body]);
592 | }
593 | case "ParameterClause": {
594 | if (n.layout[1].layout.length === 0) {
595 | return concat(path.map(print, "layout"));
596 | }
597 |
598 | const body = path.map(print, "layout");
599 | const first = body.shift();
600 | const last = body.pop();
601 |
602 | return group(
603 | concat([
604 | group(concat([indent(concat([first, softline, ...body])), softline])),
605 | last
606 | ])
607 | );
608 | }
609 | case "TypeInheritanceClause": {
610 | const body = path.map(print, "layout");
611 | const first = body.shift();
612 | return concat([first, " ", group(indent(smartJoin(" ", body)))]);
613 | }
614 | case "FunctionSignature": {
615 | return smartJoin(" ", path.map(print, "layout"));
616 | }
617 | case "ClosureSignature": {
618 | const body = path.map(print, "layout");
619 | const inKeyword = body.pop();
620 |
621 | const numberOfStatements = path
622 | .getParentNode()
623 | .layout.find(n => n.type == "CodeBlockItemList").layout.length;
624 |
625 | const printedBody = concat([join(line, body), " ", inKeyword]);
626 |
627 | // Never break for an empty closure expr
628 | if (numberOfStatements === 0) {
629 | return group(printedBody);
630 | }
631 |
632 | return group(indent(indent(concat([softline, group(printedBody)]))));
633 | }
634 | case "CatchClause": {
635 | return smartJoin(" ", path.map(print, "layout"));
636 | }
637 | case "DeferStmt":
638 | case "ValueBindingPattern":
639 | case "AttributedType":
640 | case "ReturnClause": {
641 | return group(smartJoin(" ", path.map(print, "layout")));
642 | }
643 | case "ClosureCaptureSignature":
644 | case "TupleExpr":
645 | case "TupleType":
646 | case "DictionaryExpr":
647 | case "ArrayExpr": {
648 | const list = n.layout[1];
649 |
650 | if (
651 | // Never break inside [:]
652 | !list.layout ||
653 | // Never break inside `[]` or `()`
654 | list.layout.length === 0 ||
655 | // Never break single element tuples or arrays
656 | (list.layout.length < 2 &&
657 | ["TupleExpr", "TupleType", "ArrayExpr"].includes(n.type))
658 | ) {
659 | return group(concat(path.map(print, "layout")));
660 | }
661 |
662 | n.left = n.layout[0];
663 | n.list = list;
664 | n.right = n.layout[2];
665 | n.rest = n.layout.slice(3);
666 |
667 | return group(
668 | smartJoin(" ", [
669 | concat([
670 | path.call(print, "left"),
671 | indent(concat([softline, path.call(print, "list")])),
672 | softline,
673 | path.call(print, "right")
674 | ]),
675 | ...path.map(print, "rest")
676 | ])
677 | );
678 | }
679 | case "FunctionType": {
680 | const parts = [];
681 |
682 | for (let i = 0; i < n.layout.length; i++) {
683 | const child = n.layout[i];
684 |
685 | if (child.type === "l_paren") {
686 | parts.push({
687 | type: "TupleType",
688 | layout: n.layout.slice(i, i + 3)
689 | });
690 |
691 | i += 2;
692 | } else {
693 | parts.push(child);
694 | }
695 | }
696 |
697 | n.parts = parts;
698 | return group(smartJoin(" ", path.map(print, "parts")));
699 | }
700 | case "GenericArgument":
701 | case "SameTypeRequirement":
702 | case "ConformanceRequirement":
703 | case "InheritedType":
704 | case "CaseItem":
705 | case "ClosureCaptureItem":
706 | case "ClosureParam":
707 | case "CompositionTypeElement":
708 | case "ConditionElement":
709 | case "TuplePatternElement":
710 | case "TupleTypeElement":
711 | case "ArrayElement":
712 | case "DictionaryElement":
713 | case "TupleElement":
714 | case "GenericParameter":
715 | case "FunctionCallArgument":
716 | case "FunctionParameter": {
717 | return group(
718 | smartJoin(
719 | " ",
720 | path.map(() => {
721 | return path.getValue().type === "comma" ? "" : print(path);
722 | }, "layout")
723 | )
724 | );
725 | }
726 | case "_CaseDeclElement": {
727 | const hasComma = n.layout.some(n => n.type === "comma");
728 | const hasInitializerClause = n.layout.some(
729 | n => n.type === "InitializerClause"
730 | );
731 |
732 | const body = path.map(print, "layout");
733 |
734 | if (hasComma) {
735 | body.pop();
736 | }
737 |
738 | if (hasInitializerClause) {
739 | const last = body.pop();
740 | return group(concat([concat(body), " ", last]));
741 | }
742 |
743 | return group(concat(body));
744 | }
745 | case "ClosureExpr": {
746 | const body = path.map(print, "layout");
747 | const first = body.shift();
748 | const last = body.pop();
749 | const signature = body.length === 1 ? null : body.shift();
750 | const parent = path.getParentNode();
751 | const closureIsCallee = parent.layout[0] === n;
752 |
753 | // Don't break when there's no statements, e.g. `{ _ in }`
754 | const hasStatements = n.layout.some(
755 | c => c.type === "CodeBlockItemList" && c.layout.length > 0
756 | );
757 |
758 | const hasNamedParameters = n.layout.some(
759 | c =>
760 | c.type === "ClosureSignature" &&
761 | c.layout.some(
762 | c =>
763 | c.type === "ClosureParamList" &&
764 | c.layout.some(c =>
765 | c.layout.some(c => c.type === "identifier" && c.text)
766 | )
767 | )
768 | );
769 |
770 | // Always break if parameters are named
771 | const shouldBreak =
772 | hasStatements && (closureIsCallee || hasNamedParameters);
773 |
774 | // Ensure space when trailing closure `it { ... }`
775 | const prefix =
776 | parent.type === "FunctionCallExpr" && !closureIsCallee ? " " : "";
777 |
778 | return group(
779 | concat([
780 | prefix,
781 | first,
782 | signature ? concat([" ", signature]) : "",
783 | hasStatements ? indent(concat([line, ...body])) : "",
784 | shouldBreak ? hardline : line,
785 | last
786 | ])
787 | );
788 | }
789 | case "Backtick": {
790 | return "`";
791 | }
792 | case "Tab":
793 | case "Space": {
794 | return ""; // ignore
795 | }
796 | case "Newline": {
797 | return n.value >= 2 ? hardline : "";
798 | }
799 | case "GarbageText":
800 | case "DocBlockComment":
801 | case "DocLineComment":
802 | case "BlockComment":
803 | case "LineComment": {
804 | return concat([
805 | options.leading ? "" : hardline,
806 | n.value,
807 | options.leading ? hardline : ""
808 | ]);
809 | }
810 | case "Unknown":
811 | case "UnknownType":
812 | case "UnknownExpr":
813 | case "UnknownDecl":
814 | case "UnknownStmt": {
815 | const fallback = verbatimPrint(n)
816 | .replace(/^[ \t]+/, "")
817 | .replace(/^[\n]+/, s => (s.split("\n").length >= 2 ? "\n" : ""))
818 | .replace(/\s+$/, s => (s.split("\n").length >= 2 ? "\n" : ""));
819 |
820 | const shorten = s => {
821 | if (s[0] === "\n") {
822 | s = s.slice(1);
823 | }
824 |
825 | s = fallback.replace(/\n/g, "\u23ce");
826 |
827 | if (s.length > 30) {
828 | s = s.slice(0, 30) + "\u2026";
829 | }
830 |
831 | return s;
832 | };
833 |
834 | const message = "libSyntax(" + type + "): " + shorten(fallback);
835 |
836 | if (!process.env.PRETTIER_SWIFT_RENDER_UNKNOWN) {
837 | throw new Error(message);
838 | }
839 |
840 | // eslint-disable-next-line no-console
841 | console.warn(message);
842 |
843 | if (type === "UnknownExpr") {
844 | return concat(path.map(print, "layout"));
845 | }
846 |
847 | return join(hardline, fallback.split("\n"));
848 | }
849 | case "AssignmentExpr": {
850 | return concat([" ", ...path.map(print, "layout"), " "]);
851 | }
852 | case "BinaryOperatorExpr": {
853 | const operator = n.layout[0];
854 |
855 | if (operator.type.endsWith("_unspaced")) {
856 | return concat(path.map(print, "layout"));
857 | }
858 |
859 | const allowBreak = !operator.text.endsWith("=");
860 |
861 | return concat([
862 | allowBreak ? line : " ",
863 | ...path.map(print, "layout"),
864 | " "
865 | ]);
866 | }
867 | case "MemberAccessExpr": {
868 | const parts = path.map(print, "layout");
869 | const first = parts.shift();
870 | return concat([group(first), concat(parts)]);
871 | }
872 | case "FunctionCallExpr": {
873 | if (!options.argumentsOnly && n.layout[0] && isMemberish(n.layout[0])) {
874 | n.callee = n.layout[0];
875 | n.callee.object = n.callee.layout[0];
876 |
877 | try {
878 | return printMemberChain(path, options, print);
879 | } catch (error) {
880 | throw error;
881 | }
882 | }
883 |
884 | const leftIndex = n.layout.findIndex(n => n.type === "l_paren");
885 | const rightIndex = n.layout.findIndex(n => n.type === "r_paren");
886 |
887 | if (leftIndex < 0 || rightIndex < 0) {
888 | n.start = n.layout.slice(options.argumentsOnly ? 1 : 0);
889 | return group(concat(path.map(print, "start")));
890 | }
891 |
892 | const start = options.argumentsOnly
893 | ? n.layout.slice(leftIndex, leftIndex + 1)
894 | : n.layout.slice(0, leftIndex + 1);
895 | const middle = n.layout.slice(leftIndex + 1, rightIndex);
896 | const end = n.layout.slice(rightIndex);
897 |
898 | Object.assign(n, {
899 | start,
900 | middle,
901 | end
902 | });
903 |
904 | // Optimize: Never break inside if we don't have a parameter
905 | if (middle[0] && middle[0].layout.length == 0) {
906 | return concat([...path.map(print, "start"), ...path.map(print, "end")]);
907 | }
908 |
909 | if (
910 | middle[0].layout.length == 1 &&
911 | // Optimize: Just a closure as argument (RxSwift)
912 | //
913 | // observable.subscribe(onNext: {
914 | // ...
915 | // })
916 | (middle[0].layout[0].layout.some(n => n.type === "ClosureExpr") ||
917 | // Optimize: Plain function invocation as only argument
918 | //
919 | // array.add(User(
920 | // name: "John Doe"
921 | // })
922 | middle[0].layout[0].layout.some(
923 | n =>
924 | n.type === "FunctionCallExpr" &&
925 | n.layout[0].type === "IdentifierExpr"
926 | ) ||
927 | // Optimize: Array or Dictionary expressions as only argument
928 | //
929 | // array.add([
930 | // 1,
931 | // 2,
932 | // 3
933 | // })
934 | middle[0].layout[0].layout.some(n =>
935 | ["ArrayExpr", "DictionaryExpr"].includes(n.type)
936 | ))
937 | ) {
938 | return concat([
939 | ...path.map(print, "start"),
940 | group(concat(path.map(print, "middle"))),
941 | ...path.map(print, "end")
942 | ]);
943 | }
944 |
945 | return concat([
946 | ...path.map(print, "start"),
947 | group(
948 | concat([
949 | indent(concat([softline, ...path.map(print, "middle")])),
950 | softline
951 | ])
952 | ),
953 | ...path.map(print, "end")
954 | ]);
955 | }
956 | case "TernaryExpr": {
957 | const [condition, questionMark, ifTrue, colon, ifFalse] = path.map(
958 | print,
959 | "layout"
960 | );
961 |
962 | const maybeIndent = doc =>
963 | ["ExprList", "TernaryType"].includes(parentType) ? doc : indent(doc);
964 |
965 | // Break the closing paren to keep the chain right after it:
966 | // (a
967 | // ? b
968 | // : c
969 | // ).call()
970 | const breakClosingParen = parentType == "MemberAccessExpr";
971 |
972 | return group(
973 | concat([
974 | condition,
975 | maybeIndent(
976 | concat([
977 | line,
978 | questionMark,
979 | " ",
980 | ifTrue.type === "TernaryExpr" ? ifBreak("", "(") : "",
981 | align(2, group(ifTrue)),
982 | ifTrue.type === "TernaryExpr" ? ifBreak("", "(") : "",
983 | line,
984 | colon,
985 | " ",
986 | align(2, ifFalse)
987 | ])
988 | ),
989 | breakClosingParen ? softline : ""
990 | ])
991 | );
992 | }
993 |
994 | case "SwitchCaseLabel": {
995 | const body = path.map(print, "layout");
996 | const first = body.shift();
997 | const last = body.pop();
998 | return concat([first, " ", ...body, last]);
999 | }
1000 |
1001 | // Types without special formatting but with grouping behavior
1002 | case "_AvailabilityExpr":
1003 | case "_GenericTypeExpr":
1004 | case "_RefExpr":
1005 | case "_SelectorExpr":
1006 | case "AccessorParameter":
1007 | case "AssignExpr":
1008 | case "Attribute":
1009 | case "DeclNameArgument":
1010 | case "DeclNameArgumentList":
1011 | case "DeclNameArguments":
1012 | case "DeclRefExpr":
1013 | case "DiscardAssignmentExpr":
1014 | case "DotSelfExpr":
1015 | case "ExpressionSegment":
1016 | case "ForcedValueExpr":
1017 | case "ForceTryExpr":
1018 | case "GenericArgumentClause":
1019 | case "GenericParameterClause":
1020 | case "IdentifierExpr":
1021 | case "IfExpr":
1022 | case "ImplicitMemberExpr":
1023 | case "InOutExpr":
1024 | case "OptionalChainingExpr":
1025 | case "OptionalTryExpr":
1026 | case "PostfixUnaryExpr":
1027 | case "PrefixOperatorExpr":
1028 | case "PrefixUnaryExpr":
1029 | case "SequenceExpr":
1030 | case "SpecializeExpr":
1031 | case "StringInterpolationSegments":
1032 | case "StringSegment":
1033 | case "SubscriptExpr":
1034 | case "SuperRefExpr":
1035 | case "TupleElementExpr":
1036 | case "TypeExpr":
1037 | case "UnresolvedMemberExpr":
1038 | case "UnresolvedPatternExpr":
1039 | return group(concat(path.map(print, "layout")));
1040 |
1041 | // Types without special formatting and no grouping behavior
1042 | case "_CaseBlock":
1043 | case "_ClassTypeIdentifier":
1044 | case "AccessPath":
1045 | case "AccessPathComponent":
1046 | case "ArrayType":
1047 | case "BooleanLiteralExpr":
1048 | case "CodeBlockItem":
1049 | case "DeclModifier":
1050 | case "ElseifDirectiveClauseList":
1051 | case "ExpressionPattern":
1052 | case "FloatLiteralExpr":
1053 | case "IdentifierPattern":
1054 | case "ImplicitlyUnwrappedOptionalType":
1055 | case "IntegerLiteralExpr":
1056 | case "InterpolatedStringLiteralExpr":
1057 | case "IsTypePattern":
1058 | case "KeyPathExpr":
1059 | case "MemberTypeIdentifier":
1060 | case "MetatypeType":
1061 | case "NilLiteralExpr":
1062 | case "ObjcKeyPathExpr":
1063 | case "ObjcName":
1064 | case "ObjcNamePiece":
1065 | case "OptionalType":
1066 | case "PoundFileExpr":
1067 | case "PoundFunctionExpr":
1068 | case "PoundLineExpr":
1069 | case "SimpleTypeIdentifier":
1070 | case "StringLiteralExpr":
1071 | case "SwitchDefaultLabel":
1072 | case "TuplePattern":
1073 | case "WildcardPattern":
1074 | return concat(path.map(print, "layout"));
1075 |
1076 | default:
1077 | if (type.endsWith("LiteralExpr")) {
1078 | // eslint-disable-next-line no-console
1079 | console.warn("Unknown literal expression: " + type);
1080 | return concat(path.map(print, "layout"));
1081 | } else if (type.endsWith("Expr")) {
1082 | // eslint-disable-next-line no-console
1083 | console.warn("Unknown expression: " + type);
1084 | return group(concat(path.map(print, "layout")));
1085 | }
1086 |
1087 | // Maybe someone forgot to add it here:
1088 | // swift/Syntax/Serialization/SyntaxSerialization.h
1089 | // struct ObjectTraits
1090 | error("Unhandled type: " + type);
1091 | return concat(path.map(print, "layout"));
1092 | }
1093 | }
1094 |
1095 | function error(message) {
1096 | // eslint-disable-next-line no-console
1097 | console.error(message);
1098 |
1099 | if (!process.env.IGNORE_ERRORS) {
1100 | throw new Error(message);
1101 | }
1102 | }
1103 |
1104 | module.exports = {
1105 | genericPrint
1106 | };
1107 |
--------------------------------------------------------------------------------
/src/printer/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const comments = require("prettier/src/main/comments");
4 | const { concat } = require("./builders");
5 | const { genericPrint } = require("./generic");
6 |
7 | module.exports = function(path, options, print) {
8 | const n = path.getValue();
9 |
10 | if (!n) {
11 | throw new Error(
12 | "Illegal navigation into " +
13 | path.getName() +
14 | " from " +
15 | path.getParentNode().type
16 | );
17 | }
18 |
19 | return concat([
20 | ...(n.leadingTrivia
21 | ? path.map(
22 | (path, options) =>
23 | genericPrint(
24 | path,
25 | Object.assign({}, options, { leading: true }),
26 | print
27 | ),
28 | "leadingTrivia"
29 | )
30 | : []),
31 | comments.printComments(
32 | path,
33 | () => genericPrint(path, options, print),
34 | options
35 | ),
36 | ...(n.trailingTrivia ? path.map(print, "trailingTrivia") : [])
37 | ]);
38 | };
39 |
--------------------------------------------------------------------------------
/src/printer/tokens.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const tokens = {
4 | amp_prefix: "&",
5 | l_paren: "(",
6 | r_paren: ")",
7 | l_brace: "{",
8 | r_brace: "}",
9 | l_square: "[",
10 | r_square: "]",
11 | l_angle: "<",
12 | r_angle: ">",
13 | arrow: "->",
14 | eof: "",
15 | colon: ":",
16 | comma: ",",
17 | equal: "=",
18 | period: ".",
19 | period_prefix: ".",
20 | question_postfix: "?",
21 | exclaim_postfix: "!",
22 | at_sign: "@",
23 | semi: ";",
24 | question_infix: "?",
25 | string_quote: '"',
26 | backslash: "\\",
27 | string_interpolation_anchor: ")",
28 | multiline_string_quote: '"""'
29 | };
30 |
31 | const poundPrefix = "pound_";
32 |
33 | const keywordPrefix = "kw_";
34 |
35 | function printToken(token) {
36 | if (typeof token.text !== "undefined") {
37 | return token.text;
38 | }
39 |
40 | const type = token.type;
41 |
42 | if (tokens.hasOwnProperty(type)) {
43 | return tokens[type];
44 | } else if (type.startsWith(poundPrefix)) {
45 | const keyword = type.slice(poundPrefix.length);
46 | return "#" + keyword;
47 | } else if (type.startsWith(keywordPrefix)) {
48 | return type.slice(keywordPrefix.length);
49 | }
50 |
51 | throw new Error(
52 | "Don't know how to express " +
53 | JSON.stringify(type) +
54 | ":\n" +
55 | JSON.stringify(token, null, 2)
56 | );
57 | }
58 |
59 | module.exports = {
60 | printToken,
61 | tokens
62 | };
63 |
--------------------------------------------------------------------------------
/src/printer/verbatim.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const assert = require("assert");
4 | const { printToken } = require("./tokens");
5 |
6 | const characters = {
7 | Newline: "\n",
8 | Tab: "\t",
9 | Space: " ",
10 | Backtick: "`"
11 | };
12 |
13 | function triviaPrint(n) {
14 | const type = n.type || n.kind;
15 |
16 | switch (type) {
17 | case "Newline":
18 | case "Tab":
19 | case "Space":
20 | case "Backtick":
21 | return Array(n.value)
22 | .fill(characters[type])
23 | .join("");
24 | case "GarbageText":
25 | case "DocBlockComment":
26 | case "DocLineComment":
27 | case "BlockComment":
28 | case "LineComment":
29 | return n.value;
30 | default:
31 | throw new Error(
32 | "Unexpected trivium: " + type + "\n" + JSON.stringify(n, null, 2)
33 | );
34 | }
35 | }
36 |
37 | function verbatimPrint(n) {
38 | if (!n) {
39 | return "";
40 | } else if (n.presence === "Missing") {
41 | return "";
42 | } else if (n.presence) {
43 | assert.equal(n.presence, "Present");
44 | }
45 |
46 | let result = "";
47 |
48 | if (n.leadingTrivia) {
49 | result += n.leadingTrivia.map(triviaPrint).join("");
50 | }
51 |
52 | if (n.token) {
53 | result += printToken(n);
54 | } else if (n.tokenKind) {
55 | result += printToken(
56 | Object.assign({}, n.tokenKind, { type: n.tokenKind.kind })
57 | );
58 | } else {
59 | result += n.layout.map(verbatimPrint).join("");
60 | }
61 |
62 | if (n.trailingTrivia) {
63 | result += n.trailingTrivia.map(triviaPrint).join("");
64 | }
65 |
66 | return result;
67 | }
68 |
69 | module.exports = {
70 | verbatimPrint
71 | };
72 |
--------------------------------------------------------------------------------
/tests/accessors/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`accessors.swift 1`] = `
4 | class Instance {
5 | public func foo() {}
6 | private func foo() {}
7 | internal func foo() {}
8 | public dynamic func foo() {}
9 | public var foo: String { return "123" }
10 | public private(set) var foo: String { return "123" }
11 | @objc public var foo: String { return "123" }
12 | @objc public var foo: String {
13 | get {
14 | return "123"
15 | }
16 | set(v) {
17 | print(v)
18 | }
19 | }
20 | @IBOutlet public var foo: String {
21 | didSet {
22 | print(oldValue, foo)
23 | }
24 | }
25 | }
26 | class Class {
27 | public class func foo() {}
28 | private class func foo() {}
29 | internal class func foo() {}
30 | }
31 | class Static {
32 | public static func foo() {}
33 | private static func foo() {}
34 | internal static func foo() {}
35 | }
36 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37 | class Instance {
38 | public func foo() { }
39 | private func foo() { }
40 | internal func foo() { }
41 | public dynamic func foo() { }
42 | public var foo: String {
43 | return "123"
44 | }
45 | public private(set) var foo: String {
46 | return "123"
47 | }
48 | @objc public var foo: String {
49 | return "123"
50 | }
51 | @objc public var foo: String {
52 | get {
53 | return "123"
54 | }
55 | set(v) {
56 | print(v)
57 | }
58 | }
59 | @IBOutlet public var foo: String {
60 | didSet {
61 | print(oldValue, foo)
62 | }
63 | }
64 | }
65 | class Class {
66 | public class func foo() { }
67 | private class func foo() { }
68 | internal class func foo() { }
69 | }
70 | class Static {
71 | public static func foo() { }
72 | private static func foo() { }
73 | internal static func foo() { }
74 | }
75 |
76 | `;
77 |
--------------------------------------------------------------------------------
/tests/accessors/accessors.swift:
--------------------------------------------------------------------------------
1 | class Instance {
2 | public func foo() {}
3 | private func foo() {}
4 | internal func foo() {}
5 | public dynamic func foo() {}
6 | public var foo: String { return "123" }
7 | public private(set) var foo: String { return "123" }
8 | @objc public var foo: String { return "123" }
9 | @objc public var foo: String {
10 | get {
11 | return "123"
12 | }
13 | set(v) {
14 | print(v)
15 | }
16 | }
17 | @IBOutlet public var foo: String {
18 | didSet {
19 | print(oldValue, foo)
20 | }
21 | }
22 | }
23 | class Class {
24 | public class func foo() {}
25 | private class func foo() {}
26 | internal class func foo() {}
27 | }
28 | class Static {
29 | public static func foo() {}
30 | private static func foo() {}
31 | internal static func foo() {}
32 | }
33 |
--------------------------------------------------------------------------------
/tests/accessors/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/args/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`args.swift 1`] = `
4 | func foo() {}
5 | func foo() -> Void {}
6 | func foo(bar: Int) {}
7 | func foo(bar: Int) -> Void {}
8 | func foo(_ bar: Int) {}
9 | func foo(_ bar: Int) -> Void {}
10 | func foo(_ bar: Int = 3) {}
11 | func foo(_ bar: Int = 3) -> Void {}
12 | func foo(_ bar: Int, baz: Int) {}
13 | func foo(_ bar: Int, baz: Int) -> Void {}
14 | func foo(_ bar: Int, _ baz: Int) {}
15 | func foo(_ bar: Int, _ baz: Int) -> Void {}
16 |
17 | func foo(f: @escaping (Int) -> Int) {}
18 | func foo(f: @escaping (Int) -> Int) -> Void {}
19 | func foo(_ f: @escaping (Int) -> Int) {}
20 | func foo(_ f: @escaping (Int) -> Int) -> Void {}
21 | func foo(_ bar: Int, f: @escaping () -> ()) {}
22 | func foo(_ bar: Int, f: @escaping () -> ()) -> Void {}
23 |
24 | func theQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOverTheVeryLazyDog() {
25 | print()
26 | }
27 |
28 | func theQuickBrownFoxJumpsOverTheLazyDog(theQuickBrownFoxJumpsOverTheLazyDog: TheQuickBrownFoxJumpsOverTheLazyDog) {
29 | print()
30 | }
31 |
32 | func theQuickBrownFoxJumpsOverTheLazyDog(theQuickBrownFoxJumpsOverTheLazyDog: TheQuickBrownFoxJumpsOverTheLazyDog) -> Bool {
33 | return true
34 | }
35 |
36 | func == (lhs: Record, rhs: Record) -> Bool {
37 | return lhs.id == rhs.id
38 | }
39 |
40 | func isZeroLength(string: String) -> Bool {
41 | return string.isEmpty
42 | }
43 |
44 | class Somewhere {
45 | func hello(title: String = "Hello", _ args: Any...) throws -> SomeType where Foo.E == Bar {
46 | let arr = [
47 | 1,2,3
48 | ]
49 | let dict = [:]()
50 | _ = hello2(whoCreatesAFunction: "That is sooooooo veeeery long that we need to", breakItToFitTheScreenComeOnNowBREAKBREAKBREAK: false)
51 | return 42
52 | }
53 |
54 | func hello2(whoCreatesAFunction: String = "That is so long that we need to", breakItToFitTheScreenComeOnNowBREAKBREAKBREAK: Bool) -> Int {
55 | print(msg: "hi") {
56 | print("ho")
57 | }
58 |
59 | print(msg: "hi") {
60 | // or what?
61 | print("ho")
62 | }
63 |
64 | return 42
65 | }
66 |
67 | func theQuickBrownFoxJumpsOverTheLazyDog(theQuickBrownFox: TheQuickBrownFox) -> JumpsOverTheLazyDog<(whetherTheDogIsLazyOrNot: Bool, theMaybeLazyDog: TheMaybeLazyDog)> {
68 | print("jump")
69 | }
70 | }
71 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72 | func foo() { }
73 | func foo() -> Void { }
74 | func foo(bar: Int) { }
75 | func foo(bar: Int) -> Void { }
76 | func foo(_ bar: Int) { }
77 | func foo(_ bar: Int) -> Void { }
78 | func foo(_ bar: Int = 3) { }
79 | func foo(_ bar: Int = 3) -> Void { }
80 | func foo(_ bar: Int, baz: Int) { }
81 | func foo(_ bar: Int, baz: Int) -> Void { }
82 | func foo(_ bar: Int, _ baz: Int) { }
83 | func foo(_ bar: Int, _ baz: Int) -> Void { }
84 |
85 | func foo(f: @escaping (Int) -> Int) { }
86 | func foo(f: @escaping (Int) -> Int) -> Void { }
87 | func foo(_ f: @escaping (Int) -> Int) { }
88 | func foo(_ f: @escaping (Int) -> Int) -> Void { }
89 | func foo(_ bar: Int, f: @escaping () -> ()) { }
90 | func foo(_ bar: Int, f: @escaping () -> ()) -> Void { }
91 |
92 | func theQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOverTheVeryLazyDog() {
93 | print()
94 | }
95 |
96 | func theQuickBrownFoxJumpsOverTheLazyDog(
97 | theQuickBrownFoxJumpsOverTheLazyDog: TheQuickBrownFoxJumpsOverTheLazyDog
98 | ) {
99 | print()
100 | }
101 |
102 | func theQuickBrownFoxJumpsOverTheLazyDog(
103 | theQuickBrownFoxJumpsOverTheLazyDog: TheQuickBrownFoxJumpsOverTheLazyDog
104 | ) -> Bool {
105 | return true
106 | }
107 |
108 | func == (lhs: Record, rhs: Record) -> Bool {
109 | return lhs.id == rhs.id
110 | }
111 |
112 | func isZeroLength(string: String) -> Bool {
113 | return string.isEmpty
114 | }
115 |
116 | class Somewhere {
117 | func hello(
118 | title: String = "Hello",
119 | _ args: Any...
120 | ) throws -> SomeType where Foo.E == Bar {
121 | let arr = [1, 2, 3]
122 | let dict = [:]()
123 | _ = hello2(
124 | whoCreatesAFunction: "That is sooooooo veeeery long that we need to",
125 | breakItToFitTheScreenComeOnNowBREAKBREAKBREAK: false
126 | )
127 | return 42
128 | }
129 |
130 | func hello2(
131 | whoCreatesAFunction: String = "That is so long that we need to",
132 | breakItToFitTheScreenComeOnNowBREAKBREAKBREAK: Bool
133 | ) -> Int {
134 | print(msg: "hi") { print("ho") }
135 |
136 | print(msg: "hi") {
137 | // or what?
138 | print("ho")
139 | }
140 |
141 | return 42
142 | }
143 |
144 | func theQuickBrownFoxJumpsOverTheLazyDog(
145 | theQuickBrownFox: TheQuickBrownFox
146 | ) -> JumpsOverTheLazyDog<(
147 | whetherTheDogIsLazyOrNot: Bool,
148 | theMaybeLazyDog: TheMaybeLazyDog
149 | )> {
150 | print("jump")
151 | }
152 | }
153 |
154 | `;
155 |
--------------------------------------------------------------------------------
/tests/args/args.swift:
--------------------------------------------------------------------------------
1 | func foo() {}
2 | func foo() -> Void {}
3 | func foo(bar: Int) {}
4 | func foo(bar: Int) -> Void {}
5 | func foo(_ bar: Int) {}
6 | func foo(_ bar: Int) -> Void {}
7 | func foo(_ bar: Int = 3) {}
8 | func foo(_ bar: Int = 3) -> Void {}
9 | func foo(_ bar: Int, baz: Int) {}
10 | func foo(_ bar: Int, baz: Int) -> Void {}
11 | func foo(_ bar: Int, _ baz: Int) {}
12 | func foo(_ bar: Int, _ baz: Int) -> Void {}
13 |
14 | func foo(f: @escaping (Int) -> Int) {}
15 | func foo(f: @escaping (Int) -> Int) -> Void {}
16 | func foo(_ f: @escaping (Int) -> Int) {}
17 | func foo(_ f: @escaping (Int) -> Int) -> Void {}
18 | func foo(_ bar: Int, f: @escaping () -> ()) {}
19 | func foo(_ bar: Int, f: @escaping () -> ()) -> Void {}
20 |
21 | func theQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOverTheVeryLazyDog() {
22 | print()
23 | }
24 |
25 | func theQuickBrownFoxJumpsOverTheLazyDog(theQuickBrownFoxJumpsOverTheLazyDog: TheQuickBrownFoxJumpsOverTheLazyDog) {
26 | print()
27 | }
28 |
29 | func theQuickBrownFoxJumpsOverTheLazyDog(theQuickBrownFoxJumpsOverTheLazyDog: TheQuickBrownFoxJumpsOverTheLazyDog) -> Bool {
30 | return true
31 | }
32 |
33 | func == (lhs: Record, rhs: Record) -> Bool {
34 | return lhs.id == rhs.id
35 | }
36 |
37 | func isZeroLength(string: String) -> Bool {
38 | return string.isEmpty
39 | }
40 |
41 | class Somewhere {
42 | func hello(title: String = "Hello", _ args: Any...) throws -> SomeType where Foo.E == Bar {
43 | let arr = [
44 | 1,2,3
45 | ]
46 | let dict = [:]()
47 | _ = hello2(whoCreatesAFunction: "That is sooooooo veeeery long that we need to", breakItToFitTheScreenComeOnNowBREAKBREAKBREAK: false)
48 | return 42
49 | }
50 |
51 | func hello2(whoCreatesAFunction: String = "That is so long that we need to", breakItToFitTheScreenComeOnNowBREAKBREAKBREAK: Bool) -> Int {
52 | print(msg: "hi") {
53 | print("ho")
54 | }
55 |
56 | print(msg: "hi") {
57 | // or what?
58 | print("ho")
59 | }
60 |
61 | return 42
62 | }
63 |
64 | func theQuickBrownFoxJumpsOverTheLazyDog(theQuickBrownFox: TheQuickBrownFox) -> JumpsOverTheLazyDog<(whetherTheDogIsLazyOrNot: Bool, theMaybeLazyDog: TheMaybeLazyDog)> {
65 | print("jump")
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tests/args/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/arrays/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`arrays.swift 1`] = `
4 | let oneElement = [42]
5 | let twoElements = ["apple", "banana"]
6 | let someArrayExpressionThatShouldNotBreak = ["becauseItHasSomeVeryLongElementButThatsTheOnlyOne"]
7 | let someArrayExpressionThatShouldBreak = ["becauseItHasSoLongElementsInItThatItHasTo", "andNotJustSingleOne"]
8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 | let oneElement = [42]
10 | let twoElements = ["apple", "banana"]
11 | let someArrayExpressionThatShouldNotBreak = ["becauseItHasSomeVeryLongElementButThatsTheOnlyOne"]
12 | let someArrayExpressionThatShouldBreak = [
13 | "becauseItHasSoLongElementsInItThatItHasTo",
14 | "andNotJustSingleOne"
15 | ]
16 |
17 | `;
18 |
19 | exports[`arrays.swift 2`] = `
20 | let oneElement = [42]
21 | let twoElements = ["apple", "banana"]
22 | let someArrayExpressionThatShouldNotBreak = ["becauseItHasSomeVeryLongElementButThatsTheOnlyOne"]
23 | let someArrayExpressionThatShouldBreak = ["becauseItHasSoLongElementsInItThatItHasTo", "andNotJustSingleOne"]
24 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 | let oneElement = [42]
26 | let twoElements = ["apple", "banana"]
27 | let someArrayExpressionThatShouldNotBreak = ["becauseItHasSomeVeryLongElementButThatsTheOnlyOne"]
28 | let someArrayExpressionThatShouldBreak = [
29 | "becauseItHasSoLongElementsInItThatItHasTo",
30 | "andNotJustSingleOne",
31 | ]
32 |
33 | `;
34 |
--------------------------------------------------------------------------------
/tests/arrays/arrays.swift:
--------------------------------------------------------------------------------
1 | let oneElement = [42]
2 | let twoElements = ["apple", "banana"]
3 | let someArrayExpressionThatShouldNotBreak = ["becauseItHasSomeVeryLongElementButThatsTheOnlyOne"]
4 | let someArrayExpressionThatShouldBreak = ["becauseItHasSoLongElementsInItThatItHasTo", "andNotJustSingleOne"]
5 |
--------------------------------------------------------------------------------
/tests/arrays/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 | run_spec(__dirname, ["swift"], { trailingComma: "all" });
3 |
--------------------------------------------------------------------------------
/tests/as/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`as.swift 1`] = `
4 | let a = b as? C
5 |
6 | theQuickBrownFoxJumpsOverTheLazyDog as? TheQuickBrownFoxJumpsOverTheLazyDog
7 |
8 | let letTheQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog.theQuickBrownFoxJumpsOverTheLazyDog() as? AppViewController
9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 | let a = b
11 | as? C
12 |
13 | theQuickBrownFoxJumpsOverTheLazyDog
14 | as? TheQuickBrownFoxJumpsOverTheLazyDog
15 |
16 | let letTheQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog.theQuickBrownFoxJumpsOverTheLazyDog()
17 | as? AppViewController
18 |
19 | `;
20 |
--------------------------------------------------------------------------------
/tests/as/as.swift:
--------------------------------------------------------------------------------
1 | let a = b as? C
2 |
3 | theQuickBrownFoxJumpsOverTheLazyDog as? TheQuickBrownFoxJumpsOverTheLazyDog
4 |
5 | let letTheQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog.theQuickBrownFoxJumpsOverTheLazyDog() as? AppViewController
6 |
--------------------------------------------------------------------------------
/tests/as/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/associatedtype/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`associatedtype.swift 1`] = `
4 | protocol SomeType {
5 | associatedtype Wrapped
6 | }
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | protocol SomeType {
9 | associatedtype Wrapped
10 | }
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/associatedtype/associatedtype.swift:
--------------------------------------------------------------------------------
1 | protocol SomeType {
2 | associatedtype Wrapped
3 | }
4 |
--------------------------------------------------------------------------------
/tests/associatedtype/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/attributes/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`attributes.swift 1`] = `
4 | @testable import SomeModule
5 |
6 | @UIApplicationMain public class MyApp {}
7 |
8 | @objc public class MyApp {}
9 |
10 | @UIApplicationMain @objc public class MyApp {}
11 |
12 | @objc(PSWMyApp) public class MyApp {}
13 |
14 | class SomeClass {
15 | @available(iOS 8, OSX 10.10, *) public func function() {}
16 |
17 | @discardableResult public func function() {}
18 |
19 | @objc public var property: String
20 |
21 | @objc(psw_property) public let property: String
22 |
23 | internal var active: Bool {
24 | @objc(isActive) get {}
25 | set {}
26 | }
27 | }
28 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29 | @testable import SomeModule
30 |
31 | @UIApplicationMain
32 | public class MyApp { }
33 |
34 | @objc public class MyApp { }
35 |
36 | @UIApplicationMain
37 | @objc
38 | public class MyApp { }
39 |
40 | @objc(PSWMyApp)
41 | public class MyApp { }
42 |
43 | class SomeClass {
44 | @available(iOS 8, OSX 10.10, *)
45 | public func function() { }
46 |
47 | @discardableResult
48 | public func function() { }
49 |
50 | @objc public var property: String
51 |
52 | @objc(psw_property)
53 | public let property: String
54 |
55 | internal var active: Bool {
56 | @objc(isActive)
57 | get { }
58 | set { }
59 | }
60 | }
61 |
62 | `;
63 |
--------------------------------------------------------------------------------
/tests/attributes/attributes.swift:
--------------------------------------------------------------------------------
1 | @testable import SomeModule
2 |
3 | @UIApplicationMain public class MyApp {}
4 |
5 | @objc public class MyApp {}
6 |
7 | @UIApplicationMain @objc public class MyApp {}
8 |
9 | @objc(PSWMyApp) public class MyApp {}
10 |
11 | class SomeClass {
12 | @available(iOS 8, OSX 10.10, *) public func function() {}
13 |
14 | @discardableResult public func function() {}
15 |
16 | @objc public var property: String
17 |
18 | @objc(psw_property) public let property: String
19 |
20 | internal var active: Bool {
21 | @objc(isActive) get {}
22 | set {}
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/attributes/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/backtick/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`backtick.swift 1`] = `
4 | call { [weak self] in
5 | let \`self\` = self
6 | print(self)
7 | }
8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 | call { [weak self] in
10 | let \`self\` = self
11 | print(self)
12 | }
13 |
14 | `;
15 |
--------------------------------------------------------------------------------
/tests/backtick/backtick.swift:
--------------------------------------------------------------------------------
1 | call { [weak self] in
2 | let `self` = self
3 | print(self)
4 | }
5 |
--------------------------------------------------------------------------------
/tests/backtick/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/bugs/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`bugs.swift 1`] = `
4 | #!/usr/bin/swift
5 | button.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)
6 |
7 | print(optional ?? [])
8 |
9 | let x = PublishSubject()
10 |
11 | NSNumber.self
12 |
13 | class Spinner: UIView {
14 | let rotationDuration = 0.9;
15 | }
16 |
17 | protocol Something {
18 | associatedtype T1
19 | associatedtype T2: Foo, Bar
20 | }
21 |
22 | [1, 2, 3].map { (partial) -> String in
23 | "\\(partial)"
24 | }
25 |
26 | let firstTupleElement = tuple.0
27 |
28 | let semicolons = foo();
29 |
30 | [1,2,3].map { $0 + 1 }
31 |
32 | let foo = { bar(); baz() }
33 |
34 | let sub = { (\`self\`) -> Disposable in self.subscribe() }
35 |
36 | @available(iOS 8, OSX 10.10, *)
37 | func foo(x: Int) -> String {
38 |
39 | }
40 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41 | #!/usr/bin/swift
42 | button.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)
43 |
44 | print(optional ?? [])
45 |
46 | let x = PublishSubject()
47 |
48 | NSNumber.self
49 |
50 | class Spinner: UIView {
51 | let rotationDuration = 0.9
52 | }
53 |
54 | protocol Something {
55 | associatedtype T1
56 | associatedtype T2: Foo, Bar
57 | }
58 |
59 | [1, 2, 3].map { partial -> String in
60 | "\\(partial)"
61 | }
62 |
63 | let firstTupleElement = tuple.0
64 |
65 | let semicolons = foo();
66 |
67 | [1, 2, 3].map { $0 + 1 }
68 |
69 | let foo = {
70 | bar();
71 | baz()
72 | }
73 |
74 | let sub = { \`self\` -> Disposable in
75 | self.subscribe()
76 | }
77 |
78 | @available(iOS 8, OSX 10.10, *)
79 | func foo(x: Int) -> String { }
80 |
81 | `;
82 |
83 | exports[`closure_with_parens.swift 1`] = `
84 | let foo = { (_, user: User) in print(user) }
85 |
86 | // This will not be formatted because the above line prevents us
87 | // from processing this whole file.
88 | let array = [1,2,3]
89 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
90 |
91 | let foo = { (_, user: User) in print(user) }
92 |
93 | // This will not be formatted because the above line prevents us
94 | // from processing this whole file.
95 | let array = [1,2,3]
96 |
97 | `;
98 |
--------------------------------------------------------------------------------
/tests/bugs/bugs.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/swift
2 | button.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)
3 |
4 | print(optional ?? [])
5 |
6 | let x = PublishSubject()
7 |
8 | NSNumber.self
9 |
10 | class Spinner: UIView {
11 | let rotationDuration = 0.9;
12 | }
13 |
14 | protocol Something {
15 | associatedtype T1
16 | associatedtype T2: Foo, Bar
17 | }
18 |
19 | [1, 2, 3].map { (partial) -> String in
20 | "\(partial)"
21 | }
22 |
23 | let firstTupleElement = tuple.0
24 |
25 | let semicolons = foo();
26 |
27 | [1,2,3].map { $0 + 1 }
28 |
29 | let foo = { bar(); baz() }
30 |
31 | let sub = { (`self`) -> Disposable in self.subscribe() }
32 |
33 | @available(iOS 8, OSX 10.10, *)
34 | func foo(x: Int) -> String {
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/tests/bugs/closure_with_parens.swift:
--------------------------------------------------------------------------------
1 | let foo = { (_, user: User) in print(user) }
2 |
3 | // This will not be formatted because the above line prevents us
4 | // from processing this whole file.
5 | let array = [1,2,3]
6 |
--------------------------------------------------------------------------------
/tests/bugs/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/captures/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`captures.swift 1`] = `
4 | do {
5 | do {
6 | do {
7 | do {
8 | theQuickBrownFoxJumpsOverTheLazyDog { [capture, something] () -> TheQuickBrownFoxJumpsOverTheLazyDog in
9 | print(1)
10 | print(2)
11 | }
12 | }
13 | }
14 | }
15 | }~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 | do {
17 | do {
18 | do {
19 | do {
20 | theQuickBrownFoxJumpsOverTheLazyDog {
21 | [capture, something]
22 | ()
23 | -> TheQuickBrownFoxJumpsOverTheLazyDog in
24 | print(1)
25 | print(2)
26 | }
27 | }
28 | }
29 | }
30 | }
31 |
32 | `;
33 |
--------------------------------------------------------------------------------
/tests/captures/captures.swift:
--------------------------------------------------------------------------------
1 | do {
2 | do {
3 | do {
4 | do {
5 | theQuickBrownFoxJumpsOverTheLazyDog { [capture, something] () -> TheQuickBrownFoxJumpsOverTheLazyDog in
6 | print(1)
7 | print(2)
8 | }
9 | }
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/tests/captures/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/chains/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`chains.swift 1`] = `
4 | Observable.just(theQuickBrownFoxJumpsOverTheLazyDog).map(
5 | theQuickBrownFoxJumpsOverTheLazyDog
6 | )
7 |
8 | Observable.just(theQuickBrownFoxJumpsOverTheLazyDog)
9 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
10 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
11 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
12 |
13 | Observable.using(resource) { return theQuickBrownFoxJumpsOverTheLazyDog }
14 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
15 |
16 | // The first line will be formatted weirdly,
17 | // but prettier JS exposes the same issue.
18 | TheQuickBrownFoxJumpsOverTheLazyDog
19 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
20 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
21 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 | Observable.just(theQuickBrownFoxJumpsOverTheLazyDog).map(
24 | theQuickBrownFoxJumpsOverTheLazyDog
25 | )
26 |
27 | Observable.just(theQuickBrownFoxJumpsOverTheLazyDog)
28 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
29 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
30 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
31 |
32 | Observable.using(resource) {
33 | return theQuickBrownFoxJumpsOverTheLazyDog
34 | }.map(theQuickBrownFoxJumpsOverTheLazyDog)
35 |
36 | // The first line will be formatted weirdly,
37 | // but prettier JS exposes the same issue.
38 | TheQuickBrownFoxJumpsOverTheLazyDog.map(
39 | theQuickBrownFoxJumpsOverTheLazyDog
40 | )
41 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
42 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
43 |
44 | `;
45 |
--------------------------------------------------------------------------------
/tests/chains/chains.swift:
--------------------------------------------------------------------------------
1 | Observable.just(theQuickBrownFoxJumpsOverTheLazyDog).map(
2 | theQuickBrownFoxJumpsOverTheLazyDog
3 | )
4 |
5 | Observable.just(theQuickBrownFoxJumpsOverTheLazyDog)
6 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
7 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
8 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
9 |
10 | Observable.using(resource) { return theQuickBrownFoxJumpsOverTheLazyDog }
11 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
12 |
13 | // The first line will be formatted weirdly,
14 | // but prettier JS exposes the same issue.
15 | TheQuickBrownFoxJumpsOverTheLazyDog
16 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
17 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
18 | .map(theQuickBrownFoxJumpsOverTheLazyDog)
19 |
--------------------------------------------------------------------------------
/tests/chains/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/comments/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`chain.swift 1`] = `
4 | chain // next to root
5 | .map({ true /* inside */ }) // same line as map
6 | .map { true }
7 | // after
8 | .map { true }
9 | // after all
10 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 | chain // next to root
12 | .map({
13 | true /* inside */
14 | }) // same line as map
15 | .map { true }
16 | // after
17 | .map { true }
18 | // after all
19 |
20 | `;
21 |
22 | exports[`comments.swift 1`] = `
23 | // before print("1")
24 | print("1") // same line as print("1")
25 | // after print("1")
26 |
27 | print("2")
28 |
29 | // with empty line
30 |
31 | print("3")
32 |
33 | print/* inside */(/* inside */"4")
34 |
35 | print(
36 | "5" // after argument
37 | )
38 |
39 | chain
40 | // after root
41 | .map { true }
42 | // after
43 |
44 | self.map { true }
45 |
46 | let answer = /* deep */ /* blue */ 42
47 |
48 | let array = [
49 | 0, // 0%
50 | 25,
51 | 50, // 50%,
52 | 75,
53 | 100 // 100%
54 | ]
55 |
56 | if something {
57 | print("ifTrue")
58 | }
59 | // comment
60 | else {
61 | print("ifFalse")
62 | }
63 |
64 | // asd
65 | a()
66 |
67 | // available-check
68 | if #available(iOS 11.3, tvOS 11.3, *) {
69 | print("available")
70 | }
71 |
72 | class SomeClass {
73 | var property: String {
74 | get {
75 | // comment
76 | return "hello"
77 | }
78 | }
79 | }
80 |
81 | let loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore = [
82 | "loremIpsumDolorSitAmetConsecteturAdipiscing", // elitSedDoEiusmodTemporIncididuntUtLabore
83 | "loremIpsumDolorSitAmetConsecteturAdipiscing" // elitSedDoEiusmodTemporIncididuntUtLabore
84 | ]
85 |
86 | private enum EditEvent : CustomDebugStringConvertible {
87 | case inserted // can't be found in old sections
88 | }
89 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
90 | // before print("1")
91 | print("1") // same line as print("1")
92 | // after print("1")
93 |
94 | print("2")
95 |
96 | // with empty line
97 |
98 | print("3")
99 |
100 | print(/* inside */ /* inside */ "4")
101 |
102 | print(
103 | "5" // after argument
104 | )
105 |
106 | chain
107 | // after root
108 | .map { true }
109 | // after
110 |
111 | self.map { true }
112 |
113 | let answer = /* deep */ /* blue */ 42
114 |
115 | let array = [
116 | 0, // 0%
117 | 25,
118 | 50, // 50%,
119 | 75,
120 | 100 // 100%
121 | ]
122 |
123 | if something {
124 | print("ifTrue")
125 | } else // comment
126 | {
127 | print("ifFalse")
128 | }
129 |
130 | // asd
131 | a()
132 |
133 | // available-check
134 | if #available(iOS 11.3, tvOS 11.3, *) {
135 | print("available")
136 | }
137 |
138 | class SomeClass {
139 | var property: String {
140 | get {
141 | // comment
142 | return "hello"
143 | }
144 | }
145 | }
146 |
147 | let loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore = [
148 | "loremIpsumDolorSitAmetConsecteturAdipiscing", // elitSedDoEiusmodTemporIncididuntUtLabore
149 | "loremIpsumDolorSitAmetConsecteturAdipiscing" // elitSedDoEiusmodTemporIncididuntUtLabore
150 | ]
151 |
152 | private enum EditEvent: CustomDebugStringConvertible {
153 | case inserted // can't be found in old sections
154 | }
155 |
156 | `;
157 |
158 | exports[`only.swift 1`] = `
159 | // Only comment
160 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161 | // Only comment
162 |
163 | `;
164 |
--------------------------------------------------------------------------------
/tests/comments/chain.swift:
--------------------------------------------------------------------------------
1 | chain // next to root
2 | .map({ true /* inside */ }) // same line as map
3 | .map { true }
4 | // after
5 | .map { true }
6 | // after all
7 |
--------------------------------------------------------------------------------
/tests/comments/comments.swift:
--------------------------------------------------------------------------------
1 | // before print("1")
2 | print("1") // same line as print("1")
3 | // after print("1")
4 |
5 | print("2")
6 |
7 | // with empty line
8 |
9 | print("3")
10 |
11 | print/* inside */(/* inside */"4")
12 |
13 | print(
14 | "5" // after argument
15 | )
16 |
17 | chain
18 | // after root
19 | .map { true }
20 | // after
21 |
22 | self.map { true }
23 |
24 | let answer = /* deep */ /* blue */ 42
25 |
26 | let array = [
27 | 0, // 0%
28 | 25,
29 | 50, // 50%,
30 | 75,
31 | 100 // 100%
32 | ]
33 |
34 | if something {
35 | print("ifTrue")
36 | }
37 | // comment
38 | else {
39 | print("ifFalse")
40 | }
41 |
42 | // asd
43 | a()
44 |
45 | // available-check
46 | if #available(iOS 11.3, tvOS 11.3, *) {
47 | print("available")
48 | }
49 |
50 | class SomeClass {
51 | var property: String {
52 | get {
53 | // comment
54 | return "hello"
55 | }
56 | }
57 | }
58 |
59 | let loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore = [
60 | "loremIpsumDolorSitAmetConsecteturAdipiscing", // elitSedDoEiusmodTemporIncididuntUtLabore
61 | "loremIpsumDolorSitAmetConsecteturAdipiscing" // elitSedDoEiusmodTemporIncididuntUtLabore
62 | ]
63 |
64 | private enum EditEvent : CustomDebugStringConvertible {
65 | case inserted // can't be found in old sections
66 | }
67 |
--------------------------------------------------------------------------------
/tests/comments/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/comments/only.swift:
--------------------------------------------------------------------------------
1 | // Only comment
2 |
--------------------------------------------------------------------------------
/tests/composition/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`composition.swift 1`] = `
4 | typealias AB = A & B
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 | typealias AB = A & B
7 |
8 | `;
9 |
--------------------------------------------------------------------------------
/tests/composition/composition.swift:
--------------------------------------------------------------------------------
1 | typealias AB = A & B
2 |
--------------------------------------------------------------------------------
/tests/composition/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/continue/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`continue.swift 1`] = `
4 | for i in 0...16 {
5 | continue
6 | }
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | for i in 0...16 {
9 | continue
10 | }
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/continue/continue.swift:
--------------------------------------------------------------------------------
1 | for i in 0...16 {
2 | continue
3 | }
4 |
--------------------------------------------------------------------------------
/tests/continue/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/defer/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`defer.swift 1`] = `
4 | func test() {
5 | defer { print("hi") }
6 |
7 | defer {
8 | print("hello")
9 | print("world")
10 | }
11 | }
12 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 | func test() {
14 | defer { print("hi") }
15 |
16 | defer {
17 | print("hello")
18 | print("world")
19 | }
20 | }
21 |
22 | `;
23 |
--------------------------------------------------------------------------------
/tests/defer/defer.swift:
--------------------------------------------------------------------------------
1 | func test() {
2 | defer { print("hi") }
3 |
4 | defer {
5 | print("hello")
6 | print("world")
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/defer/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/deinit/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`deinit.swift 1`] = `
4 | class Something {
5 | deinit {}
6 | deinit {
7 | print("deinit")
8 | }
9 | }
10 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 | class Something {
12 | deinit { }
13 | deinit {
14 | print("deinit")
15 | }
16 | }
17 |
18 | `;
19 |
--------------------------------------------------------------------------------
/tests/deinit/deinit.swift:
--------------------------------------------------------------------------------
1 | class Something {
2 | deinit {}
3 | deinit {
4 | print("deinit")
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/tests/deinit/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/dictionaries/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`dictionaries.swift 1`] = `
4 | let oneElement = ["answer": 42]
5 | let twoElements = ["apple": 1, "banana": 2]
6 | let someDictionaryExpressionThatShouldBreak = ["becauseItHasOneVeryLongElement": "thatForcesItToBreak"]
7 | let someDictionaryExpressionThatShouldAlsoBreak = ["because": "itHas", "soLongElementsInIt": "thatItHasTo"]
8 | let someDictionaryExpressionThatIsJustPrintedOfTheDocumentPrintWidthBoundary = [:]
9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 | let oneElement = ["answer": 42]
11 | let twoElements = ["apple": 1, "banana": 2]
12 | let someDictionaryExpressionThatShouldBreak = [
13 | "becauseItHasOneVeryLongElement": "thatForcesItToBreak"
14 | ]
15 | let someDictionaryExpressionThatShouldAlsoBreak = [
16 | "because": "itHas",
17 | "soLongElementsInIt": "thatItHasTo"
18 | ]
19 | let someDictionaryExpressionThatIsJustPrintedOfTheDocumentPrintWidthBoundary = [:]
20 |
21 | `;
22 |
23 | exports[`dictionaries.swift 2`] = `
24 | let oneElement = ["answer": 42]
25 | let twoElements = ["apple": 1, "banana": 2]
26 | let someDictionaryExpressionThatShouldBreak = ["becauseItHasOneVeryLongElement": "thatForcesItToBreak"]
27 | let someDictionaryExpressionThatShouldAlsoBreak = ["because": "itHas", "soLongElementsInIt": "thatItHasTo"]
28 | let someDictionaryExpressionThatIsJustPrintedOfTheDocumentPrintWidthBoundary = [:]
29 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 | let oneElement = ["answer": 42]
31 | let twoElements = ["apple": 1, "banana": 2]
32 | let someDictionaryExpressionThatShouldBreak = [
33 | "becauseItHasOneVeryLongElement": "thatForcesItToBreak",
34 | ]
35 | let someDictionaryExpressionThatShouldAlsoBreak = [
36 | "because": "itHas",
37 | "soLongElementsInIt": "thatItHasTo",
38 | ]
39 | let someDictionaryExpressionThatIsJustPrintedOfTheDocumentPrintWidthBoundary = [:]
40 |
41 | `;
42 |
--------------------------------------------------------------------------------
/tests/dictionaries/dictionaries.swift:
--------------------------------------------------------------------------------
1 | let oneElement = ["answer": 42]
2 | let twoElements = ["apple": 1, "banana": 2]
3 | let someDictionaryExpressionThatShouldBreak = ["becauseItHasOneVeryLongElement": "thatForcesItToBreak"]
4 | let someDictionaryExpressionThatShouldAlsoBreak = ["because": "itHas", "soLongElementsInIt": "thatItHasTo"]
5 | let someDictionaryExpressionThatIsJustPrintedOfTheDocumentPrintWidthBoundary = [:]
6 |
--------------------------------------------------------------------------------
/tests/dictionaries/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 | run_spec(__dirname, ["swift"], { trailingComma: "all" });
3 |
--------------------------------------------------------------------------------
/tests/dummy/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`dummy.swift 1`] = `
4 | // A reminder to myself on how to quickly create a throw away gui app on OSX (i.e. a single file,
5 | // w/o relying on XCode project templates
6 |
7 | //Notes: In general it is hard to know how to create a Cocoa based gui without using XCode.
8 | //This issue has existed for both Objective-C and now Swift
9 |
10 | //Furthermore, Swift<-->Cocoa syntax has changed dramatically over various Swift versions,
11 | //making stackoverflow posts unreliable
12 |
13 | //This file provides a template for creating a throw away gui app
14 |
15 | //Status: macOS only -- throw away apps for devices have many non-trivial aspects
16 |
17 | //Status: This currenty works under swift 3 + package manager (just replace the main.swift generated
18 | // with swift init --executable with this file
19 | // However, it is not currently Swifty
20 |
21 | //todo:
22 | // add metal custom view or sprite kit demo to demonstrate using more frameworks
23 |
24 | import Cocoa
25 |
26 | print("Hello, world!")
27 |
28 | //todo: remind myself what this does
29 | NSApplication.shared()
30 |
31 | //#1 status bar
32 | let statusItem = NSStatusBar.system().statusItem(withLength: NSVariableStatusItemLength).foo()
33 | statusItem.title = "Quit"
34 | // statusItem.action = #selector(NSApplication.terminate)
35 |
36 |
37 | //#2 random window (not the typical pattern)
38 | let window = NSWindow(contentRect: NSMakeRect(0, 0, 320, 200),
39 | styleMask: .titled,
40 | backing: .buffered,
41 | defer: true)
42 | window.orderFrontRegardless()
43 |
44 |
45 | //#3 App delegate (more typical pattern)
46 | class AppDel: NSObject, NSApplicationDelegate {
47 | var mainWindow: NSWindow?
48 |
49 | var foo: Bar
50 |
51 | func applicationDidFinishLaunching(_ aNotification: Notification) {
52 | print("Finished Launching")
53 |
54 |
55 | let window = NSWindow(contentRect: NSMakeRect(800, 600, 320, 200),
56 | styleMask: [.titled, .closable],
57 | backing: .buffered,
58 | defer: true)
59 | window.orderFrontRegardless()
60 | self.mainWindow = window
61 |
62 | NSApp.activate(ignoringOtherApps: true)
63 | }
64 |
65 | func applicationShouldTerminateAfterLastWindowClosed(_ app: NSApplication) -> Bool {
66 | return true
67 | }
68 |
69 | var fooProp: String {
70 | return "foo"
71 | }
72 |
73 | public override init() {
74 | super.init()
75 | }
76 |
77 | init(whitelist: @escaping Comparison = { _ -> Bool in return true }, blacklist: @escaping Comparison = { _ -> Bool in return true } ) {
78 | self.whitelist = whitelist
79 | self.blacklist = blacklist
80 | }
81 |
82 | init(endpointClosure: @escaping MoyaProvider.EndpointClosure = MoyaProvider.defaultEndpointMapping,
83 | requestClosure: @escaping MoyaProvider.RequestClosure = MoyaProvider.defaultRequestMapping) {
84 | print("foo")
85 | }
86 |
87 | deinit {
88 | print("deinit")
89 | }
90 |
91 | lazy var lazyFooProp: String = {
92 | return "foo"
93 | }()
94 |
95 | func logPath() -> URL {
96 | let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
97 | print(docs)
98 | }
99 |
100 | dynamic let artworkImageView = ListingsCollectionViewCell._artworkImageView()
101 |
102 | typealias DownloadImageClosure = (_ url: URL?, _ imageView: UIImageView) -> ()
103 | }
104 |
105 | typealias Dictionary = [String: AnyObject]
106 |
107 | NSApp.setActivationPolicy(.regular)
108 |
109 | let del = AppDel()
110 | NSApp.delegate = del
111 |
112 | NSApp.run()
113 |
114 | typealias Foo = Int
115 |
116 | func foo123() -> (String) -> Void { }
117 |
118 | enum Foo {
119 | case bar
120 | }
121 |
122 | enum FooInt: Int {
123 | case bar = 3
124 | case baz, bat = 3
125 | }
126 |
127 | extension Foo: CustomStringConvertible { }
128 | extension Observable where Element: BooleanType { }
129 |
130 | let bar1 = foo as? Int
131 | let bar2 = foo as! Int
132 | let bar3 = foo as Int
133 |
134 | if foo {
135 | print("1")
136 | } else if bar {
137 | print("2")
138 | } else {
139 | print("3")
140 | }
141 |
142 | let x = foo ? "YES" : "NO"
143 |
144 | present(vc) {}
145 |
146 | func foo(completion: @escaping (String) -> Void) { }
147 |
148 | observer.onNext((self.appViewController.presentedViewController as? FulfillmentContainerViewController) != nil)
149 |
150 | if case .leaf(let value) = node {
151 | print(value)
152 | }
153 |
154 | let o = AnyObserver { [weak self, foo] event in
155 | print(event, foo)
156 | }
157 |
158 | var requestBidderDetailsCommand = { (enabled: Observable) -> CocoaAction in
159 | appDelegate().requestBidderDetailsCommand(enabled: enabled)
160 | }
161 |
162 | let rotationAnimation = CABasicAnimation(keyPath:"transform")
163 |
164 | extension Collection where Iterator.Element: ObservableType, Iterator.Element.E: BooleanType {
165 |
166 | }
167 |
168 | guard let dollars = formatter.string(from: NSDecimalNumber(mantissa: cents, exponent: -2, isNegative: false)) else {
169 | return ""
170 | }
171 |
172 | cardHandler.cardStatus
173 | .subscribe { (event) in
174 | print(event)
175 | }
176 | .addDisposableTo(rx_disposeBag)
177 |
178 | func detectDevelopmentEnvironment() -> Bool {
179 | var developmentEnvironment = false
180 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
181 | developmentEnvironment = true
182 | #elseif os(macOS)
183 | developmentEnvironment = false
184 | #else
185 | developmentEnvironment = 32
186 | #endif
187 | return developmentEnvironment
188 | }
189 |
190 | extension UIView {
191 | public var rx_hidden: AnyObserver {
192 | return AnyObserver { [weak self] event in
193 | MainScheduler.ensureExecutingOnScheduler()
194 | }
195 | }
196 | }
197 |
198 | func didReceiveResponse(_ result: Result, target: TargetType) {
199 | print()
200 | }
201 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
202 | // A reminder to myself on how to quickly create a throw away gui app on OSX (i.e. a single file,
203 | // w/o relying on XCode project templates
204 |
205 | //Notes: In general it is hard to know how to create a Cocoa based gui without using XCode.
206 | //This issue has existed for both Objective-C and now Swift
207 |
208 | //Furthermore, Swift<-->Cocoa syntax has changed dramatically over various Swift versions,
209 | //making stackoverflow posts unreliable
210 |
211 | //This file provides a template for creating a throw away gui app
212 |
213 | //Status: macOS only -- throw away apps for devices have many non-trivial aspects
214 |
215 | //Status: This currenty works under swift 3 + package manager (just replace the main.swift generated
216 | // with swift init --executable with this file
217 | // However, it is not currently Swifty
218 |
219 | //todo:
220 | // add metal custom view or sprite kit demo to demonstrate using more frameworks
221 |
222 | import Cocoa
223 |
224 | print("Hello, world!")
225 |
226 | //todo: remind myself what this does
227 | NSApplication.shared()
228 |
229 | //#1 status bar
230 | let statusItem = NSStatusBar.system()
231 | .statusItem(withLength: NSVariableStatusItemLength)
232 | .foo()
233 | statusItem.title = "Quit"
234 | // statusItem.action = #selector(NSApplication.terminate)
235 |
236 | //#2 random window (not the typical pattern)
237 | let window = NSWindow(
238 | contentRect: NSMakeRect(0, 0, 320, 200),
239 | styleMask: .titled,
240 | backing: .buffered,
241 | defer: true
242 | )
243 | window.orderFrontRegardless()
244 |
245 | //#3 App delegate (more typical pattern)
246 | class AppDel: NSObject, NSApplicationDelegate {
247 | var mainWindow: NSWindow?
248 |
249 | var foo: Bar
250 |
251 | func applicationDidFinishLaunching(_ aNotification: Notification) {
252 | print("Finished Launching")
253 |
254 | let window = NSWindow(
255 | contentRect: NSMakeRect(800, 600, 320, 200),
256 | styleMask: [.titled, .closable],
257 | backing: .buffered,
258 | defer: true
259 | )
260 | window.orderFrontRegardless()
261 | self.mainWindow = window
262 |
263 | NSApp.activate(ignoringOtherApps: true)
264 | }
265 |
266 | func applicationShouldTerminateAfterLastWindowClosed(
267 | _ app: NSApplication
268 | ) -> Bool {
269 | return true
270 | }
271 |
272 | var fooProp: String {
273 | return "foo"
274 | }
275 |
276 | public override init() {
277 | super.init()
278 | }
279 |
280 | init(
281 | whitelist: @escaping Comparison = { _ -> Bool in
282 | return true
283 | },
284 | blacklist: @escaping Comparison = { _ -> Bool in
285 | return true
286 | }
287 | ) {
288 | self.whitelist = whitelist
289 | self.blacklist = blacklist
290 | }
291 |
292 | init(
293 | endpointClosure: @escaping MoyaProvider.EndpointClosure = MoyaProvider.defaultEndpointMapping,
294 | requestClosure: @escaping MoyaProvider.RequestClosure = MoyaProvider.defaultRequestMapping
295 | ) {
296 | print("foo")
297 | }
298 |
299 | deinit {
300 | print("deinit")
301 | }
302 |
303 | lazy var lazyFooProp: String = {
304 | return "foo"
305 | }()
306 |
307 | func logPath() -> URL {
308 | let docs = FileManager.default.urls(
309 | for: .documentDirectory,
310 | in: .userDomainMask
311 | ).last!
312 | print(docs)
313 | }
314 |
315 | dynamic let artworkImageView = ListingsCollectionViewCell._artworkImageView()
316 |
317 | typealias DownloadImageClosure = (
318 | _ url: URL?,
319 | _ imageView: UIImageView
320 | ) -> ()
321 | }
322 |
323 | typealias Dictionary = [String: AnyObject]
324 |
325 | NSApp.setActivationPolicy(.regular)
326 |
327 | let del = AppDel()
328 | NSApp.delegate = del
329 |
330 | NSApp.run()
331 |
332 | typealias Foo = Int
333 |
334 | func foo123() -> (String) -> Void { }
335 |
336 | enum Foo {
337 | case bar
338 | }
339 |
340 | enum FooInt: Int {
341 | case bar = 3
342 | case baz, bat = 3
343 | }
344 |
345 | extension Foo: CustomStringConvertible { }
346 | extension Observable where Element: BooleanType { }
347 |
348 | let bar1 = foo as? Int
349 | let bar2 = foo as! Int
350 | let bar3 = foo
351 | as Int
352 |
353 | if foo {
354 | print("1")
355 | } else if bar {
356 | print("2")
357 | } else {
358 | print("3")
359 | }
360 |
361 | let x = foo ? "YES" : "NO"
362 |
363 | present(vc) { }
364 |
365 | func foo(completion: @escaping (String) -> Void) { }
366 |
367 | observer.onNext(
368 | (self.appViewController.presentedViewController
369 | as? FulfillmentContainerViewController) != nil
370 | )
371 |
372 | if case .leaf(let value) = node {
373 | print(value)
374 | }
375 |
376 | let o = AnyObserver { [weak self, foo] event in
377 | print(event, foo)
378 | }
379 |
380 | var requestBidderDetailsCommand = {
381 | (enabled: Observable) -> CocoaAction in
382 | appDelegate().requestBidderDetailsCommand(enabled: enabled)
383 | }
384 |
385 | let rotationAnimation = CABasicAnimation(keyPath: "transform")
386 |
387 | extension Collection
388 | where Iterator.Element: ObservableType, Iterator.Element.E: BooleanType { }
389 |
390 | guard let dollars = formatter.string(from: NSDecimalNumber(
391 | mantissa: cents,
392 | exponent: -2,
393 | isNegative: false
394 | )) else { return "" }
395 |
396 | cardHandler.cardStatus
397 | .subscribe { event in
398 | print(event)
399 | }
400 | .addDisposableTo(rx_disposeBag)
401 |
402 | func detectDevelopmentEnvironment() -> Bool {
403 | var developmentEnvironment = false
404 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
405 | developmentEnvironment = true
406 | #elseif os(macOS)
407 | developmentEnvironment = false
408 | #else
409 | developmentEnvironment = 32
410 | #endif
411 | return developmentEnvironment
412 | }
413 |
414 | extension UIView {
415 | public var rx_hidden: AnyObserver {
416 | return AnyObserver { [weak self] event in
417 | MainScheduler.ensureExecutingOnScheduler()
418 | }
419 | }
420 | }
421 |
422 | func didReceiveResponse(
423 | _ result: Result,
424 | target: TargetType
425 | ) {
426 | print()
427 | }
428 |
429 | `;
430 |
--------------------------------------------------------------------------------
/tests/dummy/dummy.swift:
--------------------------------------------------------------------------------
1 | // A reminder to myself on how to quickly create a throw away gui app on OSX (i.e. a single file,
2 | // w/o relying on XCode project templates
3 |
4 | //Notes: In general it is hard to know how to create a Cocoa based gui without using XCode.
5 | //This issue has existed for both Objective-C and now Swift
6 |
7 | //Furthermore, Swift<-->Cocoa syntax has changed dramatically over various Swift versions,
8 | //making stackoverflow posts unreliable
9 |
10 | //This file provides a template for creating a throw away gui app
11 |
12 | //Status: macOS only -- throw away apps for devices have many non-trivial aspects
13 |
14 | //Status: This currenty works under swift 3 + package manager (just replace the main.swift generated
15 | // with swift init --executable with this file
16 | // However, it is not currently Swifty
17 |
18 | //todo:
19 | // add metal custom view or sprite kit demo to demonstrate using more frameworks
20 |
21 | import Cocoa
22 |
23 | print("Hello, world!")
24 |
25 | //todo: remind myself what this does
26 | NSApplication.shared()
27 |
28 | //#1 status bar
29 | let statusItem = NSStatusBar.system().statusItem(withLength: NSVariableStatusItemLength).foo()
30 | statusItem.title = "Quit"
31 | // statusItem.action = #selector(NSApplication.terminate)
32 |
33 |
34 | //#2 random window (not the typical pattern)
35 | let window = NSWindow(contentRect: NSMakeRect(0, 0, 320, 200),
36 | styleMask: .titled,
37 | backing: .buffered,
38 | defer: true)
39 | window.orderFrontRegardless()
40 |
41 |
42 | //#3 App delegate (more typical pattern)
43 | class AppDel: NSObject, NSApplicationDelegate {
44 | var mainWindow: NSWindow?
45 |
46 | var foo: Bar
47 |
48 | func applicationDidFinishLaunching(_ aNotification: Notification) {
49 | print("Finished Launching")
50 |
51 |
52 | let window = NSWindow(contentRect: NSMakeRect(800, 600, 320, 200),
53 | styleMask: [.titled, .closable],
54 | backing: .buffered,
55 | defer: true)
56 | window.orderFrontRegardless()
57 | self.mainWindow = window
58 |
59 | NSApp.activate(ignoringOtherApps: true)
60 | }
61 |
62 | func applicationShouldTerminateAfterLastWindowClosed(_ app: NSApplication) -> Bool {
63 | return true
64 | }
65 |
66 | var fooProp: String {
67 | return "foo"
68 | }
69 |
70 | public override init() {
71 | super.init()
72 | }
73 |
74 | init(whitelist: @escaping Comparison = { _ -> Bool in return true }, blacklist: @escaping Comparison = { _ -> Bool in return true } ) {
75 | self.whitelist = whitelist
76 | self.blacklist = blacklist
77 | }
78 |
79 | init(endpointClosure: @escaping MoyaProvider.EndpointClosure = MoyaProvider.defaultEndpointMapping,
80 | requestClosure: @escaping MoyaProvider.RequestClosure = MoyaProvider.defaultRequestMapping) {
81 | print("foo")
82 | }
83 |
84 | deinit {
85 | print("deinit")
86 | }
87 |
88 | lazy var lazyFooProp: String = {
89 | return "foo"
90 | }()
91 |
92 | func logPath() -> URL {
93 | let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
94 | print(docs)
95 | }
96 |
97 | dynamic let artworkImageView = ListingsCollectionViewCell._artworkImageView()
98 |
99 | typealias DownloadImageClosure = (_ url: URL?, _ imageView: UIImageView) -> ()
100 | }
101 |
102 | typealias Dictionary = [String: AnyObject]
103 |
104 | NSApp.setActivationPolicy(.regular)
105 |
106 | let del = AppDel()
107 | NSApp.delegate = del
108 |
109 | NSApp.run()
110 |
111 | typealias Foo = Int
112 |
113 | func foo123() -> (String) -> Void { }
114 |
115 | enum Foo {
116 | case bar
117 | }
118 |
119 | enum FooInt: Int {
120 | case bar = 3
121 | case baz, bat = 3
122 | }
123 |
124 | extension Foo: CustomStringConvertible { }
125 | extension Observable where Element: BooleanType { }
126 |
127 | let bar1 = foo as? Int
128 | let bar2 = foo as! Int
129 | let bar3 = foo as Int
130 |
131 | if foo {
132 | print("1")
133 | } else if bar {
134 | print("2")
135 | } else {
136 | print("3")
137 | }
138 |
139 | let x = foo ? "YES" : "NO"
140 |
141 | present(vc) {}
142 |
143 | func foo(completion: @escaping (String) -> Void) { }
144 |
145 | observer.onNext((self.appViewController.presentedViewController as? FulfillmentContainerViewController) != nil)
146 |
147 | if case .leaf(let value) = node {
148 | print(value)
149 | }
150 |
151 | let o = AnyObserver { [weak self, foo] event in
152 | print(event, foo)
153 | }
154 |
155 | var requestBidderDetailsCommand = { (enabled: Observable) -> CocoaAction in
156 | appDelegate().requestBidderDetailsCommand(enabled: enabled)
157 | }
158 |
159 | let rotationAnimation = CABasicAnimation(keyPath:"transform")
160 |
161 | extension Collection where Iterator.Element: ObservableType, Iterator.Element.E: BooleanType {
162 |
163 | }
164 |
165 | guard let dollars = formatter.string(from: NSDecimalNumber(mantissa: cents, exponent: -2, isNegative: false)) else {
166 | return ""
167 | }
168 |
169 | cardHandler.cardStatus
170 | .subscribe { (event) in
171 | print(event)
172 | }
173 | .addDisposableTo(rx_disposeBag)
174 |
175 | func detectDevelopmentEnvironment() -> Bool {
176 | var developmentEnvironment = false
177 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
178 | developmentEnvironment = true
179 | #elseif os(macOS)
180 | developmentEnvironment = false
181 | #else
182 | developmentEnvironment = 32
183 | #endif
184 | return developmentEnvironment
185 | }
186 |
187 | extension UIView {
188 | public var rx_hidden: AnyObserver {
189 | return AnyObserver { [weak self] event in
190 | MainScheduler.ensureExecutingOnScheduler()
191 | }
192 | }
193 | }
194 |
195 | func didReceiveResponse(_ result: Result, target: TargetType) {
196 | print()
197 | }
198 |
--------------------------------------------------------------------------------
/tests/dummy/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/enum/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`enum.swift 1`] = `
4 | enum Edible {
5 | case apple
6 | case banana, cucumber
7 | }
8 |
9 | enum Count {
10 | case zero, one
11 | case some(i16: Int16), more(i32: Int32), many(Int64)
12 | }
13 |
14 | enum DifferentCount: Int {
15 | case zero = 0
16 | // libSyntax can't parse this yet:
17 | // case one = 1, two = 2
18 | case three = 3
19 | }
20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 | enum Edible {
22 | case apple
23 | case banana, cucumber
24 | }
25 |
26 | enum Count {
27 | case zero, one
28 | case some(i16: Int16), more(i32: Int32), many(Int64)
29 | }
30 |
31 | enum DifferentCount: Int {
32 | case zero = 0
33 | // libSyntax can't parse this yet:
34 | // case one = 1, two = 2
35 | case three = 3
36 | }
37 |
38 | `;
39 |
--------------------------------------------------------------------------------
/tests/enum/enum.swift:
--------------------------------------------------------------------------------
1 | enum Edible {
2 | case apple
3 | case banana, cucumber
4 | }
5 |
6 | enum Count {
7 | case zero, one
8 | case some(i16: Int16), more(i32: Int32), many(Int64)
9 | }
10 |
11 | enum DifferentCount: Int {
12 | case zero = 0
13 | // libSyntax can't parse this yet:
14 | // case one = 1, two = 2
15 | case three = 3
16 | }
17 |
--------------------------------------------------------------------------------
/tests/enum/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/extensions/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`extensions.swift 1`] = `
4 | extension Foo {}
5 | public extension Foo {}
6 | extension Foo: Swift.Error {}
7 |
8 | public final class Artist: NSObject, JSONAbleType {}
9 |
10 | @objc
11 | class OnlineProvider where Target: Moya.TargetType {}
12 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 | extension Foo { }
14 | public extension Foo { }
15 | extension Foo: Swift.Error { }
16 |
17 | public final class Artist: NSObject, JSONAbleType { }
18 |
19 | @objc class OnlineProvider where Target: Moya.TargetType { }
20 |
21 | `;
22 |
--------------------------------------------------------------------------------
/tests/extensions/extensions.swift:
--------------------------------------------------------------------------------
1 | extension Foo {}
2 | public extension Foo {}
3 | extension Foo: Swift.Error {}
4 |
5 | public final class Artist: NSObject, JSONAbleType {}
6 |
7 | @objc
8 | class OnlineProvider where Target: Moya.TargetType {}
9 |
--------------------------------------------------------------------------------
/tests/extensions/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/for_in/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`for_in.swift 1`] = `
4 | for e0 in [1, 2, 3] { print(e0) }
5 |
6 | for e1 in [1, 2, 3] {
7 | print(e1)
8 | }
9 |
10 | for e2 in elements {
11 | print(e2)
12 | }
13 |
14 | for e2 in elements where e2 % 2 == 0 {
15 | print(e2)
16 | }
17 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 | for e0 in [1, 2, 3] {
19 | print(e0)
20 | }
21 |
22 | for e1 in [1, 2, 3] {
23 | print(e1)
24 | }
25 |
26 | for e2 in elements {
27 | print(e2)
28 | }
29 |
30 | for e2 in elements where e2 % 2 == 0 {
31 | print(e2)
32 | }
33 |
34 | `;
35 |
--------------------------------------------------------------------------------
/tests/for_in/for_in.swift:
--------------------------------------------------------------------------------
1 | for e0 in [1, 2, 3] { print(e0) }
2 |
3 | for e1 in [1, 2, 3] {
4 | print(e1)
5 | }
6 |
7 | for e2 in elements {
8 | print(e2)
9 | }
10 |
11 | for e2 in elements where e2 % 2 == 0 {
12 | print(e2)
13 | }
14 |
--------------------------------------------------------------------------------
/tests/for_in/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/func/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`func.swift 1`] = `
4 | func noItems() {}
5 |
6 | func singleItem() {
7 | print("bar")
8 | }
9 |
10 | func multipleItems() {
11 | print("bar")
12 | }
13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 | func noItems() { }
15 |
16 | func singleItem() {
17 | print("bar")
18 | }
19 |
20 | func multipleItems() {
21 | print("bar")
22 | }
23 |
24 | `;
25 |
--------------------------------------------------------------------------------
/tests/func/func.swift:
--------------------------------------------------------------------------------
1 | func noItems() {}
2 |
3 | func singleItem() {
4 | print("bar")
5 | }
6 |
7 | func multipleItems() {
8 | print("bar")
9 | }
10 |
--------------------------------------------------------------------------------
/tests/func/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/function_calls/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`function_calls.swift 1`] = `
4 | foo()
5 | foo(1)
6 | foo(1, bar: 2)
7 | foo(bar: 1, baz: 2)
8 | foo(bar: { _ in 3 })
9 |
10 | theQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog()))
11 | letTheQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog: [
12 | letTheQuickBrownFoxJumpsOverTheLazyDog,
13 | letTheQuickBrownFoxJumpsOverTheLazyDog
14 | ])
15 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 | foo()
17 | foo(1)
18 | foo(1, bar: 2)
19 | foo(bar: 1, baz: 2)
20 | foo(bar: { _ in 3 })
21 |
22 | theQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog()))
23 | letTheQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog: [
24 | letTheQuickBrownFoxJumpsOverTheLazyDog,
25 | letTheQuickBrownFoxJumpsOverTheLazyDog
26 | ])
27 |
28 | `;
29 |
--------------------------------------------------------------------------------
/tests/function_calls/function_calls.swift:
--------------------------------------------------------------------------------
1 | foo()
2 | foo(1)
3 | foo(1, bar: 2)
4 | foo(bar: 1, baz: 2)
5 | foo(bar: { _ in 3 })
6 |
7 | theQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog()))
8 | letTheQuickBrownFoxJumpsOverTheLazyDog(letTheQuickBrownFoxJumpsOverTheLazyDog: [
9 | letTheQuickBrownFoxJumpsOverTheLazyDog,
10 | letTheQuickBrownFoxJumpsOverTheLazyDog
11 | ])
12 |
--------------------------------------------------------------------------------
/tests/function_calls/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/generic_where_clause/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`generic_where_clause.swift 1`] = `
4 | extension ShapedFruit where Shape: Pear {
5 |
6 | }
7 |
8 | extension TheQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOverTheLazyDog where TheLazyDog: VeryLazyDog {
9 |
10 | }
11 |
12 | class Fox {
13 | func jump(over: Dog) where Dog: LazyDog {
14 |
15 | }
16 |
17 | func theQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOver() where TheLazyDog: VeryLazyDog {
18 |
19 | }
20 | }
21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 | extension ShapedFruit where Shape: Pear { }
23 |
24 | extension TheQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOverTheLazyDog
25 | where TheLazyDog: VeryLazyDog { }
26 |
27 | class Fox {
28 | func jump(over: Dog) where Dog: LazyDog { }
29 |
30 | func theQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOver()
31 | where TheLazyDog: VeryLazyDog { }
32 | }
33 |
34 | `;
35 |
--------------------------------------------------------------------------------
/tests/generic_where_clause/generic_where_clause.swift:
--------------------------------------------------------------------------------
1 | extension ShapedFruit where Shape: Pear {
2 |
3 | }
4 |
5 | extension TheQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOverTheLazyDog where TheLazyDog: VeryLazyDog {
6 |
7 | }
8 |
9 | class Fox {
10 | func jump(over: Dog) where Dog: LazyDog {
11 |
12 | }
13 |
14 | func theQuickBrownFoxJumpsOverTheLazyDogTheQuickBrownFoxJumpsOver() where TheLazyDog: VeryLazyDog {
15 |
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/generic_where_clause/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/generics/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`generics.swift 1`] = `
4 | class Instance {}
5 | class Instance {}
6 | func foo() {}
7 | func foo() {}
8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 | class Instance { }
10 | class Instance { }
11 | func foo() { }
12 | func foo() { }
13 |
14 | `;
15 |
--------------------------------------------------------------------------------
/tests/generics/generics.swift:
--------------------------------------------------------------------------------
1 | class Instance {}
2 | class Instance {}
3 | func foo() {}
4 | func foo() {}
5 |
--------------------------------------------------------------------------------
/tests/generics/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/guard/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`guard.swift 1`] = `
4 | guard let foo = bar else { return }
5 |
6 | guard let foo = bar else { return bar() }
7 |
8 | guard let foo = bar, let thisIsATriumphLetsSeeasdASDasdasdasdasdas = theWorldIsTooLargeForUs else { return bar() }
9 |
10 | // If the target is in the blacklist, don't log it.
11 | guard blacklist(target) == false else { return }
12 |
13 | do {
14 | reuseBag = DisposeBag()
15 |
16 | guard let reuseBag = reuseBag else { return }
17 |
18 | // Start with things not expected to ever change.
19 | }
20 |
21 | guard foo else { throw SomeError.error }
22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 | guard let foo = bar else { return }
24 |
25 | guard let foo = bar else { return bar() }
26 |
27 | guard
28 | let foo = bar,
29 | let thisIsATriumphLetsSeeasdASDasdasdasdasdas = theWorldIsTooLargeForUs
30 | else { return bar() }
31 |
32 | // If the target is in the blacklist, don't log it.
33 | guard blacklist(target) == false else { return }
34 |
35 | do {
36 | reuseBag = DisposeBag()
37 |
38 | guard let reuseBag = reuseBag else { return }
39 |
40 | // Start with things not expected to ever change.
41 | }
42 |
43 | guard foo else {
44 | throw SomeError.error
45 | }
46 |
47 | `;
48 |
--------------------------------------------------------------------------------
/tests/guard/guard.swift:
--------------------------------------------------------------------------------
1 | guard let foo = bar else { return }
2 |
3 | guard let foo = bar else { return bar() }
4 |
5 | guard let foo = bar, let thisIsATriumphLetsSeeasdASDasdasdasdasdas = theWorldIsTooLargeForUs else { return bar() }
6 |
7 | // If the target is in the blacklist, don't log it.
8 | guard blacklist(target) == false else { return }
9 |
10 | do {
11 | reuseBag = DisposeBag()
12 |
13 | guard let reuseBag = reuseBag else { return }
14 |
15 | // Start with things not expected to ever change.
16 | }
17 |
18 | guard foo else { throw SomeError.error }
19 |
--------------------------------------------------------------------------------
/tests/guard/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/if/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`if.swift 1`] = `
4 | if let imageDicts = json["images"].object as? Array> {
5 | print("foo")
6 | }
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | if let imageDicts = json["images"].object
9 | as? Array> {
10 | print("foo")
11 | }
12 |
13 | `;
14 |
--------------------------------------------------------------------------------
/tests/if/if.swift:
--------------------------------------------------------------------------------
1 | if let imageDicts = json["images"].object as? Array> {
2 | print("foo")
3 | }
4 |
--------------------------------------------------------------------------------
/tests/if/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/if_config_decl/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`if_config_decl.swift 1`] = `
4 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
5 | developmentEnvironment = true
6 | #elseif os(macOS)
7 | developmentEnvironment = false
8 | #else
9 | developmentEnvironment = 32
10 | #endif
11 |
12 | // This doesn't render correctly
13 | class SomeClass {
14 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
15 | func f1() {
16 | print("1")
17 | }
18 | #elseif os(macOS)
19 | func f2() {
20 | print("2")
21 | }
22 | #else
23 | func f3() {
24 | print("3")
25 | }
26 | #endif
27 | }
28 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
30 | developmentEnvironment = true
31 | #elseif os(macOS)
32 | developmentEnvironment = false
33 | #else
34 | developmentEnvironment = 32
35 | #endif
36 |
37 | // This doesn't render correctly
38 | class SomeClass {
39 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
40 | func f1() {
41 | print("1")
42 | }
43 | #elseif os(macOS)
44 | func f2() {
45 | print("2")
46 | }
47 | #else
48 | func f3() {
49 | print("3")
50 | }
51 | #endif
52 | }
53 |
54 | `;
55 |
--------------------------------------------------------------------------------
/tests/if_config_decl/if_config_decl.swift:
--------------------------------------------------------------------------------
1 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
2 | developmentEnvironment = true
3 | #elseif os(macOS)
4 | developmentEnvironment = false
5 | #else
6 | developmentEnvironment = 32
7 | #endif
8 |
9 | // This doesn't render correctly
10 | class SomeClass {
11 | #if DEBUG || (arch(i386) || arch(x86_64)) && os(iOS)
12 | func f1() {
13 | print("1")
14 | }
15 | #elseif os(macOS)
16 | func f2() {
17 | print("2")
18 | }
19 | #else
20 | func f3() {
21 | print("3")
22 | }
23 | #endif
24 | }
25 |
--------------------------------------------------------------------------------
/tests/if_config_decl/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/ignore/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`ignore.swift 1`] = `
4 | do {
5 | let identity = Matrix.create(
6 | 1, 0, 0,
7 | 0, 1, 0,
8 | 0, 0, 0
9 | ) // prettier-ignore
10 | }
11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 | do {
13 | let identity = Matrix.create(
14 | 1, 0, 0,
15 | 0, 1, 0,
16 | 0, 0, 0
17 | )
18 | }
19 |
20 | `;
21 |
--------------------------------------------------------------------------------
/tests/ignore/ignore.swift:
--------------------------------------------------------------------------------
1 | do {
2 | let identity = Matrix.create(
3 | 1, 0, 0,
4 | 0, 1, 0,
5 | 0, 0, 0
6 | ) // prettier-ignore
7 | }
8 |
--------------------------------------------------------------------------------
/tests/ignore/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/import/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`import.swift 1`] = `
4 | import Foundation
5 | @testable import SomeModule
6 |
7 | import typealias SomeModule.Something
8 | import struct SomeModule.Something
9 | import class SomeModule.Something
10 | import enum SomeModule.Something
11 | import protocol SomeModule.Something
12 | import let SomeModule.something
13 | import var SomeModule.something
14 | import func SomeModule.something
15 |
16 | import typealias SomeModule.SomeNamespace.Something
17 | import struct SomeModule.SomeNamespace.Something
18 | import class SomeModule.SomeNamespace.Something
19 | import enum SomeModule.SomeNamespace.Something
20 | import protocol SomeModule.SomeNamespace.Something
21 | import let SomeModule.SomeNamespace.something
22 | import var SomeModule.SomeNamespace.something
23 | import func SomeModule.SomeNamespace.something
24 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 | import Foundation
26 | @testable import SomeModule
27 |
28 | import typealias SomeModule.Something
29 | import struct SomeModule.Something
30 | import class SomeModule.Something
31 | import enum SomeModule.Something
32 | import protocol SomeModule.Something
33 | import let SomeModule.something
34 | import var SomeModule.something
35 | import func SomeModule.something
36 |
37 | import typealias SomeModule.SomeNamespace.Something
38 | import struct SomeModule.SomeNamespace.Something
39 | import class SomeModule.SomeNamespace.Something
40 | import enum SomeModule.SomeNamespace.Something
41 | import protocol SomeModule.SomeNamespace.Something
42 | import let SomeModule.SomeNamespace.something
43 | import var SomeModule.SomeNamespace.something
44 | import func SomeModule.SomeNamespace.something
45 |
46 | `;
47 |
--------------------------------------------------------------------------------
/tests/import/import.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | @testable import SomeModule
3 |
4 | import typealias SomeModule.Something
5 | import struct SomeModule.Something
6 | import class SomeModule.Something
7 | import enum SomeModule.Something
8 | import protocol SomeModule.Something
9 | import let SomeModule.something
10 | import var SomeModule.something
11 | import func SomeModule.something
12 |
13 | import typealias SomeModule.SomeNamespace.Something
14 | import struct SomeModule.SomeNamespace.Something
15 | import class SomeModule.SomeNamespace.Something
16 | import enum SomeModule.SomeNamespace.Something
17 | import protocol SomeModule.SomeNamespace.Something
18 | import let SomeModule.SomeNamespace.something
19 | import var SomeModule.SomeNamespace.something
20 | import func SomeModule.SomeNamespace.something
21 |
--------------------------------------------------------------------------------
/tests/import/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/init/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`init.swift 1`] = `
4 | class SomeClass {
5 | init() {
6 |
7 | }
8 |
9 | init?() {
10 | super.init()
11 | }
12 |
13 | init() throws {
14 |
15 | }
16 |
17 | public init() {
18 |
19 | }
20 |
21 | private init?() {
22 |
23 | }
24 |
25 | internal init() throws {
26 |
27 | }
28 |
29 | override init() {
30 |
31 | }
32 |
33 | required init() {
34 |
35 | }
36 |
37 | convenience init() {
38 |
39 | }
40 |
41 | public override init?() {
42 | super.init()
43 | }
44 |
45 | init(string: String) {
46 |
47 | }
48 | }
49 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50 | class SomeClass {
51 | init() { }
52 |
53 | init?() {
54 | super.init()
55 | }
56 |
57 | init() throws { }
58 |
59 | public init() { }
60 |
61 | private init?() { }
62 |
63 | internal init() throws { }
64 |
65 | override init() { }
66 |
67 | required init() { }
68 |
69 | convenience init() { }
70 |
71 | public override init?() {
72 | super.init()
73 | }
74 |
75 | init(string: String) { }
76 | }
77 |
78 | `;
79 |
--------------------------------------------------------------------------------
/tests/init/init.swift:
--------------------------------------------------------------------------------
1 | class SomeClass {
2 | init() {
3 |
4 | }
5 |
6 | init?() {
7 | super.init()
8 | }
9 |
10 | init() throws {
11 |
12 | }
13 |
14 | public init() {
15 |
16 | }
17 |
18 | private init?() {
19 |
20 | }
21 |
22 | internal init() throws {
23 |
24 | }
25 |
26 | override init() {
27 |
28 | }
29 |
30 | required init() {
31 |
32 | }
33 |
34 | convenience init() {
35 |
36 | }
37 |
38 | public override init?() {
39 | super.init()
40 | }
41 |
42 | init(string: String) {
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/init/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/is/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`is.swift 1`] = `
4 | if apple is Apple {
5 | print("Apple")
6 | }
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | if apple is Apple {
9 | print("Apple")
10 | }
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/is/is.swift:
--------------------------------------------------------------------------------
1 | if apple is Apple {
2 | print("Apple")
3 | }
4 |
--------------------------------------------------------------------------------
/tests/is/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/is_type_pattern/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`is_type_pattern.swift 1`] = `
4 | for case is Apple in fruits {
5 | print("Apple")
6 | }
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | for case isApple in fruits {
9 | print("Apple")
10 | }
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/is_type_pattern/is_type_pattern.swift:
--------------------------------------------------------------------------------
1 | for case is Apple in fruits {
2 | print("Apple")
3 | }
4 |
--------------------------------------------------------------------------------
/tests/is_type_pattern/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/keypath/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`keypath.swift 1`] = `
4 | _ = \\a.b.c
5 | _ = \\a.b[1]
6 | _ = #keyPath(a.b.c)
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | _ = \\a.b.c
9 | _ = \\a.b[1]
10 | _ = #keyPath(a.b.c)
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/keypath/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/keypath/keypath.swift:
--------------------------------------------------------------------------------
1 | _ = \a.b.c
2 | _ = \a.b[1]
3 | _ = #keyPath(a.b.c)
4 |
--------------------------------------------------------------------------------
/tests/lazy/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`lazy.swift 1`] = `
4 | class SomeClass {
5 | public lazy var isActive = Something.isActive()
6 | public private(set) lazy var isActive = { Something.isActive }()
7 | }
8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 | class SomeClass {
10 | public lazy var isActive = Something.isActive()
11 | public private(set) lazy var isActive = {
12 | Something.isActive
13 | }()
14 | }
15 |
16 | `;
17 |
--------------------------------------------------------------------------------
/tests/lazy/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/lazy/lazy.swift:
--------------------------------------------------------------------------------
1 | class SomeClass {
2 | public lazy var isActive = Something.isActive()
3 | public private(set) lazy var isActive = { Something.isActive }()
4 | }
5 |
--------------------------------------------------------------------------------
/tests/operators/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`operators.swift 1`] = `
4 | let a = b + c * d - e || f << g ?? h
5 | let a = -b
6 | let a = !b
7 |
8 | let ref = &a
9 | let ref = &_a
10 | let ref = &a[i]
11 |
12 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog - theQuickBrownFoxJumpsOverTheLazyDog
13 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog < theQuickBrownFoxJumpsOverTheLazyDog
14 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog <= theQuickBrownFoxJumpsOverTheLazyDog
15 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog != theQuickBrownFoxJumpsOverTheLazyDog
16 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog == theQuickBrownFoxJumpsOverTheLazyDog || theQuickBrownFoxJumpsOverTheLazyDog == theQuickBrownFoxJumpsOverTheLazyDog
17 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 | let a = b + c * d - e || f << g ?? h
19 | let a = -b
20 | let a = !b
21 |
22 | let ref = &a
23 | let ref = &_a
24 | let ref = &a[i]
25 |
26 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog
27 | + theQuickBrownFoxJumpsOverTheLazyDog
28 | - theQuickBrownFoxJumpsOverTheLazyDog
29 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog
30 | + theQuickBrownFoxJumpsOverTheLazyDog
31 | < theQuickBrownFoxJumpsOverTheLazyDog
32 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog
33 | + theQuickBrownFoxJumpsOverTheLazyDog <= theQuickBrownFoxJumpsOverTheLazyDog
34 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog
35 | + theQuickBrownFoxJumpsOverTheLazyDog != theQuickBrownFoxJumpsOverTheLazyDog
36 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog == theQuickBrownFoxJumpsOverTheLazyDog
37 | || theQuickBrownFoxJumpsOverTheLazyDog == theQuickBrownFoxJumpsOverTheLazyDog
38 |
39 | `;
40 |
--------------------------------------------------------------------------------
/tests/operators/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/operators/operators.swift:
--------------------------------------------------------------------------------
1 | let a = b + c * d - e || f << g ?? h
2 | let a = -b
3 | let a = !b
4 |
5 | let ref = &a
6 | let ref = &_a
7 | let ref = &a[i]
8 |
9 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog - theQuickBrownFoxJumpsOverTheLazyDog
10 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog < theQuickBrownFoxJumpsOverTheLazyDog
11 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog <= theQuickBrownFoxJumpsOverTheLazyDog
12 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog + theQuickBrownFoxJumpsOverTheLazyDog != theQuickBrownFoxJumpsOverTheLazyDog
13 | theQuickBrownFoxJumpsOverTheLazyDog = theQuickBrownFoxJumpsOverTheLazyDog == theQuickBrownFoxJumpsOverTheLazyDog || theQuickBrownFoxJumpsOverTheLazyDog == theQuickBrownFoxJumpsOverTheLazyDog
14 |
--------------------------------------------------------------------------------
/tests/optional_chaining/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`optional_chaining.swift 1`] = `
4 | foo()?.bar()
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 | foo()?.bar()
7 |
8 | `;
9 |
--------------------------------------------------------------------------------
/tests/optional_chaining/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/optional_chaining/optional_chaining.swift:
--------------------------------------------------------------------------------
1 | foo()?.bar()
2 |
--------------------------------------------------------------------------------
/tests/protocols/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`protocols.swift 1`] = `
4 | protocol SomeType {}
5 | public protocol SomeType {}
6 |
7 | protocol SomeType {
8 | var property: String
9 | }
10 |
11 | protocol SomeType {
12 | var property: String { get }
13 | }
14 |
15 | protocol SomeType {
16 | var property: String { get set }
17 | }
18 |
19 | protocol SomeType {
20 | func foo()
21 | }
22 |
23 | protocol SomeType {
24 | associatedtype E
25 | }
26 |
27 | internal protocol SomeType {
28 | associatedtype E
29 | func foo()
30 | func bar()
31 | var property: String { get set }
32 | }
33 |
34 | protocol ClassishType: class {
35 |
36 | }
37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38 | protocol SomeType { }
39 | public protocol SomeType { }
40 |
41 | protocol SomeType {
42 | var property: String
43 | }
44 |
45 | protocol SomeType {
46 | var property: String { get }
47 | }
48 |
49 | protocol SomeType {
50 | var property: String { get set }
51 | }
52 |
53 | protocol SomeType {
54 | func foo()
55 | }
56 |
57 | protocol SomeType {
58 | associatedtype E
59 | }
60 |
61 | internal protocol SomeType {
62 | associatedtype E
63 | func foo()
64 | func bar()
65 | var property: String { get set }
66 | }
67 |
68 | protocol ClassishType: class { }
69 |
70 | `;
71 |
--------------------------------------------------------------------------------
/tests/protocols/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/protocols/protocols.swift:
--------------------------------------------------------------------------------
1 | protocol SomeType {}
2 | public protocol SomeType {}
3 |
4 | protocol SomeType {
5 | var property: String
6 | }
7 |
8 | protocol SomeType {
9 | var property: String { get }
10 | }
11 |
12 | protocol SomeType {
13 | var property: String { get set }
14 | }
15 |
16 | protocol SomeType {
17 | func foo()
18 | }
19 |
20 | protocol SomeType {
21 | associatedtype E
22 | }
23 |
24 | internal protocol SomeType {
25 | associatedtype E
26 | func foo()
27 | func bar()
28 | var property: String { get set }
29 | }
30 |
31 | protocol ClassishType: class {
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/tests/repeat_while_stmt/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`repeat_while_stmt.swift 1`] = `
4 | repeat { print("ping") } while !pong
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 | repeat {
7 | print("ping")
8 | } while !pong
9 |
10 | `;
11 |
--------------------------------------------------------------------------------
/tests/repeat_while_stmt/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/repeat_while_stmt/repeat_while_stmt.swift:
--------------------------------------------------------------------------------
1 | repeat { print("ping") } while !pong
2 |
--------------------------------------------------------------------------------
/tests/specialize_expr/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`specialize_expr.swift 1`] = `
4 | var viewModel = PublishSubject()
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 | var viewModel = PublishSubject()
7 |
8 | `;
9 |
--------------------------------------------------------------------------------
/tests/specialize_expr/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/specialize_expr/specialize_expr.swift:
--------------------------------------------------------------------------------
1 | var viewModel = PublishSubject()
2 |
--------------------------------------------------------------------------------
/tests/strings/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`strings.swift 1`] = `
4 | "string"
5 |
6 | "inter\\(po)lated"
7 |
8 | """
9 | multiline
10 | string
11 | """
12 |
13 | """
14 | some
15 | \\(
16 | multi
17 | )
18 | \\(line)
19 | string
20 | """
21 |
22 | "The quick brown fox jumps over the lazy dog. The \\(quick + brown) fox jumps over the \\(String(describing: lazy)) dog."
23 |
24 | """
25 | The quick brown fox jumps over the lazy dog. The \\(quick + brown) fox jumps over the \\(String(describing: lazy)) dog.
26 | """
27 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 | "string"
29 |
30 | "inter\\(po)lated"
31 |
32 | """
33 | multiline
34 | string
35 | """
36 |
37 | """
38 | some
39 | \\(multi)
40 | \\(line)
41 | string
42 | """
43 |
44 | "The quick brown fox jumps over the lazy dog. The \\(quick + brown) fox jumps over the \\(String(describing: lazy)) dog."
45 |
46 | """
47 | The quick brown fox jumps over the lazy dog. The \\(quick + brown) fox jumps over the \\(String(describing: lazy)) dog.
48 | """
49 |
50 | `;
51 |
--------------------------------------------------------------------------------
/tests/strings/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/strings/strings.swift:
--------------------------------------------------------------------------------
1 | "string"
2 |
3 | "inter\(po)lated"
4 |
5 | """
6 | multiline
7 | string
8 | """
9 |
10 | """
11 | some
12 | \(
13 | multi
14 | )
15 | \(line)
16 | string
17 | """
18 |
19 | "The quick brown fox jumps over the lazy dog. The \(quick + brown) fox jumps over the \(String(describing: lazy)) dog."
20 |
21 | """
22 | The quick brown fox jumps over the lazy dog. The \(quick + brown) fox jumps over the \(String(describing: lazy)) dog.
23 | """
24 |
--------------------------------------------------------------------------------
/tests/subscript/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`subscript.swift 1`] = `
4 | class Basket {
5 | subscript(name: String) -> Int {
6 | return fruits[name]
7 | }
8 |
9 | subscript(name: String) -> Int {
10 | get {
11 | return fruits[name]
12 | }
13 | set(newValue) {
14 | fruits[name] = newValue
15 | }
16 | }
17 | }
18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 | class Basket {
20 | subscript(name: String) -> Int {
21 | return fruits[name]
22 | }
23 |
24 | subscript(name: String) -> Int {
25 | get {
26 | return fruits[name]
27 | }
28 | set(newValue) {
29 | fruits[name] = newValue
30 | }
31 | }
32 | }
33 |
34 | `;
35 |
--------------------------------------------------------------------------------
/tests/subscript/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/subscript/subscript.swift:
--------------------------------------------------------------------------------
1 | class Basket {
2 | subscript(name: String) -> Int {
3 | return fruits[name]
4 | }
5 |
6 | subscript(name: String) -> Int {
7 | get {
8 | return fruits[name]
9 | }
10 | set(newValue) {
11 | fruits[name] = newValue
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/switch/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`switch.swift 1`] = `
4 | do {
5 | do {
6 | switch variable {
7 | case .foo: fallthrough
8 | case .foo, .bar: break
9 | case .error(let message):
10 | fallthrough
11 | case let label as UILabel:
12 | break
13 | case _ where variable < 20: fallthrough
14 | case TheQuickBrownFoxJumpsOver.theLazyDog, TheQuickBrownFoxJumpsOver.theVeryLazyDog, TheQuickBrownFoxJumpsOver.theLaziestDog:
15 | return 123
16 | default:
17 | print(12)
18 | }
19 | }
20 | }
21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 | do {
23 | do {
24 | switch variable {
25 | case .foo:
26 | fallthrough
27 | case .foo, .bar:
28 | break
29 | case .error(let message):
30 | fallthrough
31 | case let label as UILabel:
32 | break
33 | case _ where variable < 20:
34 | fallthrough
35 | case TheQuickBrownFoxJumpsOver.theLazyDog,
36 | TheQuickBrownFoxJumpsOver.theVeryLazyDog,
37 | TheQuickBrownFoxJumpsOver.theLaziestDog:
38 | return 123
39 | default:
40 | print(12)
41 | }
42 | }
43 | }
44 |
45 | `;
46 |
--------------------------------------------------------------------------------
/tests/switch/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/switch/switch.swift:
--------------------------------------------------------------------------------
1 | do {
2 | do {
3 | switch variable {
4 | case .foo: fallthrough
5 | case .foo, .bar: break
6 | case .error(let message):
7 | fallthrough
8 | case let label as UILabel:
9 | break
10 | case _ where variable < 20: fallthrough
11 | case TheQuickBrownFoxJumpsOver.theLazyDog, TheQuickBrownFoxJumpsOver.theVeryLazyDog, TheQuickBrownFoxJumpsOver.theLaziestDog:
12 | return 123
13 | default:
14 | print(12)
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/ternary_expr/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`ternary_expr.swift 1`] = `
4 | let variable = condition ? ifTrue : ifFalse
5 |
6 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore ? ifTrue : ifFalse
7 |
8 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore ?
9 | ["loremIpsumDolorSitAmetConsectetur": "AdipiscingElitSedDoEiusmodTemporIncididuntUtLabore"] :
10 | ["loremIpsumDolorSitAmetConsectetur": "AdipiscingElitSedDoEiusmodTemporIncididuntUtLabore"]
11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 | let variable = condition ? ifTrue : ifFalse
13 |
14 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore
15 | ? ifTrue
16 | : ifFalse
17 |
18 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore
19 | ? [
20 | "loremIpsumDolorSitAmetConsectetur": "AdipiscingElitSedDoEiusmodTemporIncididuntUtLabore"
21 | ]
22 | : [
23 | "loremIpsumDolorSitAmetConsectetur": "AdipiscingElitSedDoEiusmodTemporIncididuntUtLabore"
24 | ]
25 |
26 | `;
27 |
--------------------------------------------------------------------------------
/tests/ternary_expr/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/ternary_expr/ternary_expr.swift:
--------------------------------------------------------------------------------
1 | let variable = condition ? ifTrue : ifFalse
2 |
3 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore ? ifTrue : ifFalse
4 |
5 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore ?
6 | ["loremIpsumDolorSitAmetConsectetur": "AdipiscingElitSedDoEiusmodTemporIncididuntUtLabore"] :
7 | ["loremIpsumDolorSitAmetConsectetur": "AdipiscingElitSedDoEiusmodTemporIncididuntUtLabore"]
8 |
--------------------------------------------------------------------------------
/tests/trailing_closure/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`trailing_closure.swift 1`] = `
4 | [1,2,3].map { $0 + 1 }
5 |
6 | [1,2,3].map { _ in 42 }
7 |
8 | [1,2,3].map { element in
9 | element + 2
10 | }
11 |
12 | [1,2,3].map({ element in
13 | element + 3
14 | })
15 |
16 | [1,2,3].map(transform: { element in
17 | element + 4
18 | })
19 |
20 | [1,2,3].map(transform: { (element) -> Int in
21 | element + 5
22 | })
23 |
24 | [1,2,3].map(transform: { (element: Int) -> Int in
25 | element + 6
26 | })
27 |
28 | [1,2,3].map(transform: { (element: Int) -> Int in
29 | element + somethingThatIsQuiteLong
30 | })
31 |
32 | [1,2,3].map(transform: { (element: Int) -> Int in
33 | element + somethingThatIsFarTooLongToBePrinted
34 | })
35 |
36 | [1,2,3].map(transform: { (element: Int) -> Int in
37 | let v = element + 7
38 | return v
39 | })
40 |
41 | [1, 2, 3].map { $0 + 1 }.lazy.map { $0 + 2 }.map { $0 + 3 }.map { $0 + 4 }
42 |
43 | // Can't be formatted since libSyntax reports it as UnknownExpr
44 | filter { (e) -> Bool in return value != e }
45 |
46 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore { _ in }
47 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore { [self] _ in self }
48 |
49 | Binder(self.base) { label, color in
50 | label.textColor = color
51 | }
52 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 | [1, 2, 3].map { $0 + 1 }
54 |
55 | [1, 2, 3].map { _ in 42 }
56 |
57 | [1, 2, 3].map { element in
58 | element + 2
59 | }
60 |
61 | [1, 2, 3].map({ element in
62 | element + 3
63 | })
64 |
65 | [1, 2, 3].map(transform: { element in
66 | element + 4
67 | })
68 |
69 | [1, 2, 3].map(transform: { element -> Int in
70 | element + 5
71 | })
72 |
73 | [1, 2, 3].map(transform: { (element: Int) -> Int in element + 6 })
74 |
75 | [1, 2, 3].map(transform: { (element: Int) -> Int in
76 | element + somethingThatIsQuiteLong
77 | })
78 |
79 | [1, 2, 3].map(transform: { (element: Int) -> Int in
80 | element + somethingThatIsFarTooLongToBePrinted
81 | })
82 |
83 | [1, 2, 3].map(transform: { (element: Int) -> Int in
84 | let v = element + 7
85 | return v
86 | })
87 |
88 | [1, 2, 3]
89 | .map { $0 + 1 }
90 | .lazy.map { $0 + 2 }
91 | .map { $0 + 3 }
92 | .map { $0 + 4 }
93 |
94 | // Can't be formatted since libSyntax reports it as UnknownExpr
95 | filter { e -> Bool in
96 | return value != e
97 | }
98 |
99 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore { _ in
100 | }
101 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore {
102 | [self] _ in
103 | self
104 | }
105 |
106 | Binder(self.base) { label, color in
107 | label.textColor = color
108 | }
109 |
110 | `;
111 |
--------------------------------------------------------------------------------
/tests/trailing_closure/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/trailing_closure/trailing_closure.swift:
--------------------------------------------------------------------------------
1 | [1,2,3].map { $0 + 1 }
2 |
3 | [1,2,3].map { _ in 42 }
4 |
5 | [1,2,3].map { element in
6 | element + 2
7 | }
8 |
9 | [1,2,3].map({ element in
10 | element + 3
11 | })
12 |
13 | [1,2,3].map(transform: { element in
14 | element + 4
15 | })
16 |
17 | [1,2,3].map(transform: { (element) -> Int in
18 | element + 5
19 | })
20 |
21 | [1,2,3].map(transform: { (element: Int) -> Int in
22 | element + 6
23 | })
24 |
25 | [1,2,3].map(transform: { (element: Int) -> Int in
26 | element + somethingThatIsQuiteLong
27 | })
28 |
29 | [1,2,3].map(transform: { (element: Int) -> Int in
30 | element + somethingThatIsFarTooLongToBePrinted
31 | })
32 |
33 | [1,2,3].map(transform: { (element: Int) -> Int in
34 | let v = element + 7
35 | return v
36 | })
37 |
38 | [1, 2, 3].map { $0 + 1 }.lazy.map { $0 + 2 }.map { $0 + 3 }.map { $0 + 4 }
39 |
40 | // Can't be formatted since libSyntax reports it as UnknownExpr
41 | filter { (e) -> Bool in return value != e }
42 |
43 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore { _ in }
44 | loremIpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore { [self] _ in self }
45 |
46 | Binder(self.base) { label, color in
47 | label.textColor = color
48 | }
49 |
--------------------------------------------------------------------------------
/tests/try/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`try.swift 1`] = `
4 | try somethingDangerous()
5 |
6 | _ = try? somethingDangerous()
7 |
8 | let x = try? somethingDangerous()
9 |
10 | try! somethingDangerous()
11 |
12 | let x = try! somethingDangerous()
13 |
14 | let theQuickBrownFoxJumpsOverTheLazyDog = try makeTheQuickBrownFoxJumpsOverTheLazyDog(fox: fox, dog: dog)
15 |
16 | let theQuickBrownFoxJumpsOverTheLazyDog = try? makeTheQuickBrownFoxJumpsOverTheLazyDog(fox: fox, dog: dog)
17 |
18 | let theQuickBrownFoxJumpsOverTheLazyDog = try! makeTheQuickBrownFoxJumpsOverTheLazyDog(fox: fox, dog: dog)
19 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 | try somethingDangerous()
21 |
22 | _ = try? somethingDangerous()
23 |
24 | let x = try? somethingDangerous()
25 |
26 | try! somethingDangerous()
27 |
28 | let x = try! somethingDangerous()
29 |
30 | let theQuickBrownFoxJumpsOverTheLazyDog = try makeTheQuickBrownFoxJumpsOverTheLazyDog(
31 | fox: fox,
32 | dog: dog
33 | )
34 |
35 | let theQuickBrownFoxJumpsOverTheLazyDog = try? makeTheQuickBrownFoxJumpsOverTheLazyDog(
36 | fox: fox,
37 | dog: dog
38 | )
39 |
40 | let theQuickBrownFoxJumpsOverTheLazyDog = try! makeTheQuickBrownFoxJumpsOverTheLazyDog(
41 | fox: fox,
42 | dog: dog
43 | )
44 |
45 | `;
46 |
--------------------------------------------------------------------------------
/tests/try/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/try/try.swift:
--------------------------------------------------------------------------------
1 | try somethingDangerous()
2 |
3 | _ = try? somethingDangerous()
4 |
5 | let x = try? somethingDangerous()
6 |
7 | try! somethingDangerous()
8 |
9 | let x = try! somethingDangerous()
10 |
11 | let theQuickBrownFoxJumpsOverTheLazyDog = try makeTheQuickBrownFoxJumpsOverTheLazyDog(fox: fox, dog: dog)
12 |
13 | let theQuickBrownFoxJumpsOverTheLazyDog = try? makeTheQuickBrownFoxJumpsOverTheLazyDog(fox: fox, dog: dog)
14 |
15 | let theQuickBrownFoxJumpsOverTheLazyDog = try! makeTheQuickBrownFoxJumpsOverTheLazyDog(fox: fox, dog: dog)
16 |
--------------------------------------------------------------------------------
/tests/try_catch/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`try_catch.swift 1`] = `
4 | do { try foo() } catch {}
5 |
6 | do { try foo() } catch { print(error) }
7 |
8 | do {
9 | try foo()
10 | } catch let someError as SomeError {
11 | print(someError)
12 | }
13 |
14 | do {
15 | try foo()
16 | } catch let someError as SomeError {
17 | print(someError)
18 | } catch let someOtherError as SomeOtherError {
19 | print(someOtherError)
20 | }
21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 | do {
23 | try foo()
24 | } catch { }
25 |
26 | do {
27 | try foo()
28 | } catch {
29 | print(error)
30 | }
31 |
32 | do {
33 | try foo()
34 | } catch let someError as SomeError {
35 | print(someError)
36 | }
37 |
38 | do {
39 | try foo()
40 | } catch let someError as SomeError {
41 | print(someError)
42 | } catch let someOtherError as SomeOtherError {
43 | print(someOtherError)
44 | }
45 |
46 | `;
47 |
--------------------------------------------------------------------------------
/tests/try_catch/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/try_catch/try_catch.swift:
--------------------------------------------------------------------------------
1 | do { try foo() } catch {}
2 |
3 | do { try foo() } catch { print(error) }
4 |
5 | do {
6 | try foo()
7 | } catch let someError as SomeError {
8 | print(someError)
9 | }
10 |
11 | do {
12 | try foo()
13 | } catch let someError as SomeError {
14 | print(someError)
15 | } catch let someOtherError as SomeOtherError {
16 | print(someOtherError)
17 | }
18 |
--------------------------------------------------------------------------------
/tests/tuple_expr/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`tuple_expr.swift 1`] = `
4 | let x = tuple.0
5 | let x = tuple.0.prop
6 | let x = tuple.0.prop.a
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | let x = tuple.0
9 | let x = tuple.0.prop
10 | let x = tuple.0.prop.a
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/tuple_expr/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/tuple_expr/tuple_expr.swift:
--------------------------------------------------------------------------------
1 | let x = tuple.0
2 | let x = tuple.0.prop
3 | let x = tuple.0.prop.a
4 |
--------------------------------------------------------------------------------
/tests/type_self/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`type_self.swift 1`] = `
4 | let a = SomeType.self
5 | let b = Something.SomeType.self
6 | let c = [SomeType].self
7 | let d = [SomeType: SomeType].self
8 | let e = SomeGenericType.self
9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 | let a = SomeType.self
11 | let b = Something.SomeType.self
12 | let c = [SomeType].self
13 | let d = [SomeType: SomeType].self
14 | let e = SomeGenericType.self
15 |
16 | `;
17 |
--------------------------------------------------------------------------------
/tests/type_self/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/type_self/type_self.swift:
--------------------------------------------------------------------------------
1 | let a = SomeType.self
2 | let b = Something.SomeType.self
3 | let c = [SomeType].self
4 | let d = [SomeType: SomeType].self
5 | let e = SomeGenericType.self
6 |
--------------------------------------------------------------------------------
/tests/typealias/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`typealias.swift 1`] = `
4 | typealias LetterList = String
5 | typealias StringKeyedDictionary = Dictionary
6 | public typealias LetterList = String
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | typealias LetterList = String
9 | typealias StringKeyedDictionary = Dictionary
10 | public typealias LetterList = String
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/typealias/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/typealias/typealias.swift:
--------------------------------------------------------------------------------
1 | typealias LetterList = String
2 | typealias StringKeyedDictionary = Dictionary
3 | public typealias LetterList = String
4 |
--------------------------------------------------------------------------------
/tests/underscore/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`underscore.swift 1`] = `
4 | func foo(_: String) { }
5 | func foo(_ string: String) { }
6 | _ = 32
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | func foo(_: String) { }
9 | func foo(_ string: String) { }
10 | _ = 32
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/underscore/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/underscore/underscore.swift:
--------------------------------------------------------------------------------
1 | func foo(_: String) { }
2 | func foo(_ string: String) { }
3 | _ = 32
4 |
--------------------------------------------------------------------------------
/tests/while/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`while.swift 1`] = `
4 | while true {
5 | print("always")
6 | }
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | while true {
9 | print("always")
10 | }
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/while/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/while/while.swift:
--------------------------------------------------------------------------------
1 | while true {
2 | print("always")
3 | }
4 |
--------------------------------------------------------------------------------
/tests/wildcard/__snapshots__/jsfmt.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`wildcard.swift 1`] = `
4 | for _ in 1...3 {
5 | print("Ping")
6 | }
7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 | for _ in 1...3 {
9 | print("Ping")
10 | }
11 |
12 | `;
13 |
--------------------------------------------------------------------------------
/tests/wildcard/jsfmt.spec.js:
--------------------------------------------------------------------------------
1 | run_spec(__dirname, ["swift"]);
2 |
--------------------------------------------------------------------------------
/tests/wildcard/wildcard.swift:
--------------------------------------------------------------------------------
1 | for _ in 1...3 {
2 | print("Ping")
3 | }
4 |
--------------------------------------------------------------------------------
/tests_config/raw-serializer.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const RAW = Symbol.for("raw");
4 |
5 | module.exports = {
6 | print(val) {
7 | return val[RAW];
8 | },
9 | test(val) {
10 | return (
11 | val &&
12 | Object.prototype.hasOwnProperty.call(val, RAW) &&
13 | typeof val[RAW] === "string"
14 | );
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/tests_config/run_spec.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const fs = require("fs");
4 | const { extname } = require("path");
5 | const prettier = require("prettier");
6 | const plugin = require("../src");
7 | const { massageAST } = require("prettier/src/common/clean-ast");
8 | const { normalize } = require("prettier/src/main/options");
9 |
10 | const { AST_COMPARE } = process.env;
11 |
12 | function run_spec(dirname, parsers, options) {
13 | options = Object.assign(
14 | {
15 | plugins: ["."]
16 | },
17 | options
18 | );
19 |
20 | /* instabul ignore if */
21 | if (!parsers || !parsers.length) {
22 | throw new Error(`No parsers were specified for ${dirname}`);
23 | }
24 |
25 | fs.readdirSync(dirname).forEach(filename => {
26 | const path = `${dirname}/${filename}`;
27 | if (
28 | extname(filename) !== ".snap" &&
29 | fs.lstatSync(path).isFile() &&
30 | filename[0] !== "." &&
31 | filename !== "jsfmt.spec.js"
32 | ) {
33 | const source = read(path).replace(/\r\n/g, "\n");
34 |
35 | const mergedOptions = Object.assign(mergeDefaultOptions(options || {}), {
36 | parser: parsers[0]
37 | });
38 | const output = prettyprint(source, path, mergedOptions);
39 | test(`${filename} - ${mergedOptions.parser}-verify`, () => {
40 | expect(raw(`${source + "~".repeat(80)}\n${output}`)).toMatchSnapshot(
41 | filename
42 | );
43 | });
44 |
45 | parsers.slice(1).forEach(parserName => {
46 | test(`${filename} - ${parserName}-verify`, () => {
47 | const verifyOptions = Object.assign(mergedOptions, {
48 | parser: parserName
49 | });
50 | const verifyOutput = prettyprint(source, path, verifyOptions);
51 | expect(output).toEqual(verifyOutput);
52 | });
53 | });
54 |
55 | if (AST_COMPARE) {
56 | const normalizedOptions = normalize(mergedOptions);
57 | const ast = parse(source, mergedOptions);
58 | const astMassaged = massageAST(ast, normalizedOptions);
59 | let ppastMassaged;
60 | let pperr = null;
61 | try {
62 | const ppast = parse(
63 | prettyprint(source, path, mergedOptions),
64 | mergedOptions
65 | );
66 | ppastMassaged = massageAST(ppast, normalizedOptions);
67 | } catch (e) {
68 | pperr = e.stack;
69 | }
70 |
71 | test(`${path} parse`, () => {
72 | expect(pperr).toBe(null);
73 | expect(ppastMassaged).toBeDefined();
74 | if (!ast.errors || ast.errors.length === 0) {
75 | expect(astMassaged).toEqual(ppastMassaged);
76 | }
77 | });
78 | }
79 | }
80 | });
81 | }
82 | global.run_spec = run_spec;
83 |
84 | function stripLocation(ast) {
85 | if (Array.isArray(ast)) {
86 | return ast.map(e => stripLocation(e));
87 | }
88 | if (typeof ast === "object") {
89 | const newObj = {};
90 | for (const key in ast) {
91 | if (
92 | key === "loc" ||
93 | key === "range" ||
94 | key === "raw" ||
95 | key === "comments" ||
96 | key === "parent" ||
97 | key === "prev"
98 | ) {
99 | continue;
100 | }
101 | newObj[key] = stripLocation(ast[key]);
102 | }
103 | return newObj;
104 | }
105 | return ast;
106 | }
107 |
108 | function parse(string, opts) {
109 | return stripLocation(plugin.parsers.php.parse(string, {}, opts));
110 | }
111 |
112 | function prettyprint(src, filename, options) {
113 | return prettier.format(
114 | src,
115 | Object.assign(
116 | {
117 | filepath: filename
118 | },
119 | options
120 | )
121 | );
122 | }
123 |
124 | function read(filename) {
125 | return fs.readFileSync(filename, "utf8");
126 | }
127 |
128 | /**
129 | * Wraps a string in a marker object that is used by `./raw-serializer.js` to
130 | * directly print that string in a snapshot without escaping all double quotes.
131 | * Backticks will still be escaped.
132 | */
133 | function raw(string) {
134 | if (typeof string !== "string") {
135 | throw new Error("Raw snapshots have to be strings.");
136 | }
137 | return { [Symbol.for("raw")]: string };
138 | }
139 |
140 | function mergeDefaultOptions(parserConfig) {
141 | return Object.assign(
142 | {
143 | printWidth: 80,
144 | tabWidth: 4
145 | },
146 | parserConfig
147 | );
148 | }
149 |
--------------------------------------------------------------------------------