diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 35f2b8452..594e55cda 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,13 +37,12 @@ npm run watch #### Code Tour -- `out` compiled extension code +- `out` Compiled extension code - `images` Icons, logos, etc. -- `snippets` [Bundled MongoDB Snippets][snippet guide] -- `syntaxes` [Syntax highlighting for `.mongodb` files][syntax guide] -- `src` - - `test/suite` where tests live with files names `*.test.ts` -- `scripts` project helper scripts +- `snippets` Bundled MongoDB Snippets +- `syntaxes` [Syntax highlighting](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide#injection-grammars) for MongoDB keywords +- `src/test/suite` Where tests live with '`*.test.ts`' files names +- `scripts` Project helper scripts ## Releases diff --git a/package-lock.json b/package-lock.json index fd82a0354..60155c8a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,16 +60,19 @@ "@types/enzyme": "^3.10.12", "@types/glob": "^7.2.0", "@types/jest": "^26.0.24", + "@types/micromatch": "^4.0.2", + "@types/mkdirp": "^2.0.0", "@types/mocha": "^8.2.3", "@types/node": "^14.18.29", "@types/react": "^17.0.50", "@types/react-dom": "^17.0.17", "@types/sinon": "^9.0.11", "@types/uuid": "^8.3.4", - "@types/vscode": "^1.71.0", + "@types/vscode": "^1.74.0", "@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/parser": "^5.38.0", "@vscode/test-electron": "^2.1.5", + "@vscode/vsce": "^2.16.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "autoprefixer": "^9.8.8", "buffer": "^6.0.3", @@ -96,7 +99,6 @@ "jest-transform-stub": "^2.0.0", "less": "^3.13.1", "less-loader": "^5.0.0", - "meow": "^9.0.0", "mkdirp": "^1.0.4", "mocha": "^8.4.0", "mocha-junit-reporter": "^2.0.2", @@ -119,7 +121,6 @@ "ts-loader": "^9.4.1", "ts-node": "^10.9.1", "typescript": "^4.8.3", - "vsce": "^2.11.0", "webpack": "^5.74.0", "webpack-cli": "^4.10.0", "xvfb-maybe": "^0.2.1", @@ -127,8 +128,8 @@ }, "engines": { "node": "^16.16.0", - "npm": "^8.8.0", - "vscode": "^1.71.0" + "npm": "^8.15.1", + "vscode": "^1.75.1" } }, "node_modules/@ampproject/remapping": { @@ -4096,6 +4097,12 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/braces": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.1.tgz", + "integrity": "sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==", + "dev": true + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -4354,17 +4361,30 @@ "@types/node": "*" } }, + "node_modules/@types/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==", + "dev": true, + "dependencies": { + "@types/braces": "*" + } + }, "node_modules/@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true + "node_modules/@types/mkdirp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-2.0.0.tgz", + "integrity": "sha512-c/iUqMymAlxLAyIK3u5SzrwkrkyOdv1XDc91T+b5FsY7Jr6ERhUD19jJHOhPW4GD6tmN6mFEorfSdks525pwdQ==", + "deprecated": "This is a stub types definition. mkdirp provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "mkdirp": "*" + } }, "node_modules/@types/mocha": { "version": "8.2.3", @@ -4484,9 +4504,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.71.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.71.0.tgz", - "integrity": "sha512-nB50bBC9H/x2CpwW9FzRRRDrTZ7G0/POttJojvN/LiVfzTGfLyQIje1L1QRMdFXK9G41k5UJN/1B9S4of7CSzA==", + "version": "1.75.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.1.tgz", + "integrity": "sha512-emg7wdsTFzdi+elvoyoA+Q8keEautdQHyY5LNmHVM4PTpY8JgOTVADrGVyXGepJ6dVW2OS5/xnLUWh+nZxvdiA==", "dev": true }, "node_modules/@types/webidl-conversions": { @@ -4742,6 +4762,111 @@ "node": ">=8.9.3" } }, + "node_modules/@vscode/vsce": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.18.0.tgz", + "integrity": "sha512-tUA3XoKx5xjoi3EDcngk0VUYMhvfXLhS4s7CntpLPh1qtLYtgSCexTIMUHkCy6MqyozRW98bdW3a2yHPEADRnQ==", + "dev": true, + "dependencies": { + "azure-devops-node-api": "^11.0.1", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "commander": "^6.1.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^5.1.0", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.4.23", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 14" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@vscode/vsce/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@vscode/vsce/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vscode/vsce/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@vscode/vsce/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@vscode/vsce/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, "node_modules/@vue/compiler-core": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.4.tgz", @@ -5654,15 +5779,6 @@ "node": ">= 0.4" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -6489,23 +6605,6 @@ "node": ">=6" } }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001312", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", @@ -7857,28 +7956,6 @@ "node": ">=0.10.0" } }, - "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decimal.js": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", @@ -11577,15 +11654,6 @@ "node": ">=6" } }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -14763,15 +14831,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/jest-validate/node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/jest-validate/node_modules/pretty-format": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", @@ -15256,6 +15315,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -15523,6 +15588,15 @@ "node": ">=0.10.0" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -15943,18 +16017,6 @@ "node": ">=0.10.0" } }, - "node_modules/map-obj": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", - "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/map-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", @@ -16088,170 +16150,6 @@ "node": ">= 0.10.0" } }, - "node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/normalize-package-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", - "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "resolve": "^1.20.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -16356,15 +16254,6 @@ "dom-walk": "^0.1.0" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/mingo": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/mingo/-/mingo-1.3.3.tgz", @@ -16386,20 +16275,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -20161,15 +20036,6 @@ } ] }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/raf": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -20425,19 +20291,6 @@ "node": ">= 0.10" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/redeyed": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", @@ -22261,18 +22114,6 @@ "node": ">=6" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -22893,15 +22734,6 @@ "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", "dev": true }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -23486,117 +23318,6 @@ "extsprintf": "^1.2.0" } }, - "node_modules/vsce": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.11.0.tgz", - "integrity": "sha512-pr9Y0va/HCer0tTifeqaUrK24JJSpRd6oLeF/PY6FtrY41e+lwxiAq6jfMXx4ShAZglYg2rFKoKROwa7E7SEqQ==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "markdown-it": "^12.3.2", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "vsce" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/vsce/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/vsce/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/vsce/node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/vsce/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vsce/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/vsce/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, "node_modules/vscode-jsonrpc": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz", @@ -27853,6 +27574,12 @@ "@babel/types": "^7.3.0" } }, + "@types/braces": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.1.tgz", + "integrity": "sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==", + "dev": true + }, "@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -28098,17 +27825,29 @@ "@types/node": "*" } }, + "@types/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==", + "dev": true, + "requires": { + "@types/braces": "*" + } + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true + "@types/mkdirp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-2.0.0.tgz", + "integrity": "sha512-c/iUqMymAlxLAyIK3u5SzrwkrkyOdv1XDc91T+b5FsY7Jr6ERhUD19jJHOhPW4GD6tmN6mFEorfSdks525pwdQ==", + "dev": true, + "requires": { + "mkdirp": "*" + } }, "@types/mocha": { "version": "8.2.3", @@ -28228,9 +27967,9 @@ "dev": true }, "@types/vscode": { - "version": "1.71.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.71.0.tgz", - "integrity": "sha512-nB50bBC9H/x2CpwW9FzRRRDrTZ7G0/POttJojvN/LiVfzTGfLyQIje1L1QRMdFXK9G41k5UJN/1B9S4of7CSzA==", + "version": "1.75.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.1.tgz", + "integrity": "sha512-emg7wdsTFzdi+elvoyoA+Q8keEautdQHyY5LNmHVM4PTpY8JgOTVADrGVyXGepJ6dVW2OS5/xnLUWh+nZxvdiA==", "dev": true }, "@types/webidl-conversions": { @@ -28392,6 +28131,87 @@ "unzipper": "^0.10.11" } }, + "@vscode/vsce": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.18.0.tgz", + "integrity": "sha512-tUA3XoKx5xjoi3EDcngk0VUYMhvfXLhS4s7CntpLPh1qtLYtgSCexTIMUHkCy6MqyozRW98bdW3a2yHPEADRnQ==", + "dev": true, + "requires": { + "azure-devops-node-api": "^11.0.1", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "commander": "^6.1.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "keytar": "^7.7.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^5.1.0", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.4.23", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + } + } + }, "@vue/compiler-core": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.4.tgz", @@ -29186,12 +29006,6 @@ "function-bind": "^1.1.1" } }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -29872,17 +29686,6 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "devOptional": true }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, "caniuse-lite": { "version": "1.0.30001312", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", @@ -30953,24 +30756,6 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - } - } - }, "decimal.js": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", @@ -33953,12 +33738,6 @@ "har-schema": "^2.0.0" } }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -36806,12 +36585,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, "pretty-format": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", @@ -37025,6 +36798,12 @@ "minimist": "^1.2.5" } }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -37237,6 +37016,12 @@ } } }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -37614,12 +37399,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", - "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", - "dev": true - }, "map-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", @@ -37735,134 +37514,6 @@ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", "dev": true }, - "meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "normalize-package-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", - "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "resolve": "^1.20.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, "merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -37939,12 +37590,6 @@ "dom-walk": "^0.1.0" } }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, "mingo": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/mingo/-/mingo-1.3.3.tgz", @@ -37963,17 +37608,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -40934,12 +40568,6 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true - }, "raf": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -41142,16 +40770,6 @@ "resolve": "^1.9.0" } }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, "redeyed": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", @@ -42628,15 +42246,6 @@ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -43123,12 +42732,6 @@ "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", "dev": true }, - "trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true - }, "trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -43580,92 +43183,6 @@ "extsprintf": "^1.2.0" } }, - "vsce": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.11.0.tgz", - "integrity": "sha512-pr9Y0va/HCer0tTifeqaUrK24JJSpRd6oLeF/PY6FtrY41e+lwxiAq6jfMXx4ShAZglYg2rFKoKROwa7E7SEqQ==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "markdown-it": "^12.3.2", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - } - } - }, "vscode-jsonrpc": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz", diff --git a/package.json b/package.json index 1b350c90d..187963ed4 100644 --- a/package.json +++ b/package.json @@ -62,28 +62,15 @@ "reformat": "prettier --write ." }, "engines": { - "vscode": "^1.71.0", + "vscode": "^1.75.1", "node": "^16.16.0", - "npm": "^8.8.0" + "npm": "^8.15.1" }, "activationEvents": [ - "onCommand:mdb.connect", - "onCommand:mdb.connectWithURI", - "onCommand:mdb.openOverviewPage", - "onCommand:mdb.createPlayground", - "onCommand:mdb.addConnection", - "onCommand:mdb.addConnectionWithURI", - "onCommand:mdb.disconnect", - "onCommand:mdb.removeConnection", - "onCommand:mdb.openMongoDBShell", - "onCommand:mdb.saveMongoDBDocument", - "onCommand:mdb.insertObjectIdToEditor", - "onCommand:mdb.generateObjectIdToClipboard", "onView:mongoDB", - "onView:mongoDBConnectionExplorer", - "onView:mongoDBPlaygroundsExplorer", "onLanguage:json", - "onLanguage:mongodb" + "onLanguage:javascript", + "onLanguage:plaintext" ], "contributes": { "viewsContainers": { @@ -125,17 +112,6 @@ } ], "languages": [ - { - "id": "mongodb", - "aliases": [ - "MongoDB", - "mongodb" - ], - "extensions": [ - ".mongodb" - ], - "configuration": "./languages/mongodb-language-configuration.json" - }, { "id": "terraform", "aliases": [ @@ -149,14 +125,16 @@ ], "grammars": [ { - "language": "mongodb", - "path": "./syntaxes/mongodb.tmLanguage.json", - "scopeName": "source.mongodb" + "path": "./syntaxes/mongodbInjection.tmLanguage.json", + "scopeName": "mongodb.injection", + "injectTo": [ + "source.js" + ] } ], "snippets": [ { - "language": "mongodb", + "language": "javascript", "path": "./snippets/stage-autocompleter.json" }, { @@ -648,7 +626,7 @@ { "command": "mdb.runPlayground", "group": "navigation", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" } ], "commandPalette": [ @@ -658,27 +636,31 @@ }, { "command": "mdb.runSelectedPlaygroundBlocks", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" }, { "command": "mdb.runAllPlaygroundBlocks", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" + }, + { + "command": "mdb.exportToRuby", + "when": "mdb.isPlayground == true" }, { "command": "mdb.exportToPython", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" }, { "command": "mdb.exportToJava", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" }, { "command": "mdb.exportToCsharp", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" }, { "command": "mdb.exportToNode", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" }, { "command": "mdb.refreshPlaygroundsFromTreeView", @@ -835,19 +817,19 @@ "command": "mdb.runSelectedPlaygroundBlocks", "key": "ctrl+alt+s", "mac": "cmd+alt+s", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" }, { "command": "mdb.runAllPlaygroundBlocks", "key": "ctrl+alt+r", "mac": "cmd+alt+r", - "when": "editorLangId == mongodb" + "when": "mdb.isPlayground == true" }, { "command": "mdb.saveMongoDBDocument", "key": "ctrl+s", "mac": "cmd+s", - "when": "editorLangId == json" + "when": "mdb.isPlayground == true" } ], "capabilities": { @@ -1045,16 +1027,19 @@ "@types/enzyme": "^3.10.12", "@types/glob": "^7.2.0", "@types/jest": "^26.0.24", + "@types/micromatch": "^4.0.2", + "@types/mkdirp": "^2.0.0", "@types/mocha": "^8.2.3", "@types/node": "^14.18.29", "@types/react": "^17.0.50", "@types/react-dom": "^17.0.17", "@types/sinon": "^9.0.11", "@types/uuid": "^8.3.4", - "@types/vscode": "^1.71.0", + "@types/vscode": "^1.74.0", "@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/parser": "^5.38.0", "@vscode/test-electron": "^2.1.5", + "@vscode/vsce": "^2.16.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "autoprefixer": "^9.8.8", "buffer": "^6.0.3", @@ -1081,7 +1066,6 @@ "jest-transform-stub": "^2.0.0", "less": "^3.13.1", "less-loader": "^5.0.0", - "meow": "^9.0.0", "mkdirp": "^1.0.4", "mocha": "^8.4.0", "mocha-junit-reporter": "^2.0.2", @@ -1104,7 +1088,6 @@ "ts-loader": "^9.4.1", "ts-node": "^10.9.1", "typescript": "^4.8.3", - "vsce": "^2.11.0", "webpack": "^5.74.0", "webpack-cli": "^4.10.0", "xvfb-maybe": "^0.2.1", diff --git a/scripts/update-grammar.ts b/scripts/update-grammar.ts old mode 100755 new mode 100644 index c838da410..ad89ab40e --- a/scripts/update-grammar.ts +++ b/scripts/update-grammar.ts @@ -1,60 +1,55 @@ -#! /usr/bin/env ts-node - -import path = require('path'); -import mkdirp = require('mkdirp'); -import ora = require('ora'); -import download = require('download'); -import meow = require('meow'); - -import formatError from '../src/utils/formatError'; - -const DEFAULT_DEST = path.join(__dirname, '..', 'syntaxes'); - -const languageURL = - 'https://raw.githubusercontent.com/mongodb-js/vscode-mongodb-language/master/syntaxes/mongodb.tmLanguage.json'; - -const cli = meow( - ` - Downloads the latest mongodb.tmLanguage.json from mongodb-js/vscode-mongodb-language - - Usage - $ update-grammar.ts - - Options - --dest Directory to download to [Default: ${DEFAULT_DEST}] - --src URL of mongodb.tmLanguage.json [Default: ${languageURL}] - - Examples - $ ./update-grammar.ts - ℹ Downlading latest mongodb.tmLanguage.json - ✔ Downloaded to /Users/lucas/vsc/syntaxes/mongodb.tmLanguage.json -`, - { - flags: { - dest: { - default: DEFAULT_DEST, - }, - url: { - default: languageURL, - }, +import path from 'path'; +import mkdirp from 'mkdirp'; +import ora from 'ora'; +import fs from 'fs'; +import { promisify } from 'util'; + +import { + ACCUMULATORS, + CONVERSION_OPERATORS, + EXPRESSION_OPERATORS, + QUERY_OPERATORS, + STAGE_OPERATORS, +} from '@mongodb-js/mongodb-constants'; + +const writeFile = promisify(fs.writeFile); +const SYNTAXES_DIR = path.join(__dirname, '..', 'syntaxes'); + +const mongodbeywords = [ + ...ACCUMULATORS, + ...CONVERSION_OPERATORS, + ...EXPRESSION_OPERATORS, + ...QUERY_OPERATORS, + ...STAGE_OPERATORS, +]; + +const injectionGrammar = { + scopeName: 'mongodb.injection', + injectionSelector: 'L:meta.objectliteral.js', + patterns: [{ include: '#object-member' }], + repository: { + 'object-member': { + patterns: mongodbeywords.map((keyword) => ({ + name: 'meta.object.member.mongodb', + match: `\\${keyword.name}\\b`, + captures: { + 0: { + name: `keyword.other.${keyword.name}.mongodb`, + }, + }, + })), }, - } -); + }, +}; (async () => { - await mkdirp(DEFAULT_DEST); - - const ui = ora().info('Downlading latest mongodb.tmLanguage.json').start(); - - try { - await download(cli.flags.url, cli.flags.dest); - ui.succeed( - `Downloaded to ${path.join( - cli.flags.dest as string, - 'mongodb.tmLanguage.json' - )}` - ); - } catch (error) { - ui.fail(`Download failed: ${formatError(error).message}`); - } + const ui = ora().start(); + ui.info('Creating the MongoDB injection grammar...'); + await mkdirp(SYNTAXES_DIR); + ui.succeed(`The '${SYNTAXES_DIR}' folder has been created`); + await writeFile( + `${SYNTAXES_DIR}/mongodbInjection.tmLanguage.json`, + JSON.stringify(injectionGrammar, null, 2) + ); + ui.succeed('MongoDB injection grammar has been saved'); })(); diff --git a/scripts/update-snippets.ts b/scripts/update-snippets.ts old mode 100755 new mode 100644 index 30afeb679..943ed3462 --- a/scripts/update-snippets.ts +++ b/scripts/update-snippets.ts @@ -1,5 +1,3 @@ -#! /usr/bin/env ts-node - import path from 'path'; import mkdirp from 'mkdirp'; import ora from 'ora'; diff --git a/src/editors/activeConnectionCodeLensProvider.ts b/src/editors/activeConnectionCodeLensProvider.ts index 0013db8e3..4710b108a 100644 --- a/src/editors/activeConnectionCodeLensProvider.ts +++ b/src/editors/activeConnectionCodeLensProvider.ts @@ -1,6 +1,8 @@ import * as vscode from 'vscode'; +import { TextEditor } from 'vscode'; import EXTENSION_COMMANDS from '../commands'; import ConnectionController from '../connectionController'; +import { isPlayground } from '../utils/playground'; export default class ActiveConnectionCodeLensProvider implements vscode.CodeLensProvider @@ -8,23 +10,38 @@ export default class ActiveConnectionCodeLensProvider _connectionController: ConnectionController; _onDidChangeCodeLenses: vscode.EventEmitter = new vscode.EventEmitter(); + activeTextEditor?: TextEditor; readonly onDidChangeCodeLenses: vscode.Event = this._onDidChangeCodeLenses.event; constructor(connectionController: ConnectionController) { this._connectionController = connectionController; + this.activeTextEditor = vscode.window.activeTextEditor; vscode.workspace.onDidChangeConfiguration(() => { this._onDidChangeCodeLenses.fire(); }); } + setActiveTextEditor(activeTextEditor?: TextEditor) { + this.activeTextEditor = activeTextEditor; + this._onDidChangeCodeLenses.fire(); + } + refresh(): void { this._onDidChangeCodeLenses.fire(); } + isPlayground(): boolean { + return isPlayground(this.activeTextEditor?.document.uri); + } + provideCodeLenses(): vscode.CodeLens[] { + if (!this.isPlayground()) { + return []; + } + const codeLens = new vscode.CodeLens(new vscode.Range(0, 0, 0, 0)); let message = ''; diff --git a/src/editors/editorsController.ts b/src/editors/editorsController.ts index caa8ed2d6..63528b809 100644 --- a/src/editors/editorsController.ts +++ b/src/editors/editorsController.ts @@ -3,7 +3,7 @@ import { EJSON } from 'bson'; import ActiveConnectionCodeLensProvider from './activeConnectionCodeLensProvider'; import ExportToLanguageCodeLensProvider from './exportToLanguageCodeLensProvider'; -import CodeActionProvider from './codeActionProvider'; +import PlaygroundSelectedCodeActionProvider from './playgroundSelectedCodeActionProvider'; import ConnectionController from '../connectionController'; import CollectionDocumentsCodeLensProvider from './collectionDocumentsCodeLensProvider'; import CollectionDocumentsOperationsStore from './collectionDocumentsOperationsStore'; @@ -83,7 +83,7 @@ export function getViewCollectionDocumentsUri( * new editors and the data they need. It also manages active editors. */ export default class EditorsController { - _codeActionProvider: CodeActionProvider; + _playgroundSelectedCodeActionProvider: PlaygroundSelectedCodeActionProvider; _connectionController: ConnectionController; _playgroundController: PlaygroundController; _collectionDocumentsOperationsStore = @@ -110,7 +110,7 @@ export default class EditorsController { playgroundResultViewProvider: PlaygroundResultProvider, activeConnectionCodeLensProvider: ActiveConnectionCodeLensProvider, exportToLanguageCodeLensProvider: ExportToLanguageCodeLensProvider, - codeActionProvider: CodeActionProvider, + codeActionProvider: PlaygroundSelectedCodeActionProvider, editDocumentCodeLensProvider: EditDocumentCodeLensProvider ) { log.info('activating...'); @@ -143,7 +143,7 @@ export default class EditorsController { new CollectionDocumentsCodeLensProvider( this._collectionDocumentsOperationsStore ); - this._codeActionProvider = codeActionProvider; + this._playgroundSelectedCodeActionProvider = codeActionProvider; vscode.workspace.onDidCloseTextDocument((e) => { const uriParams = new URLSearchParams(e.uri.query); @@ -400,7 +400,7 @@ export default class EditorsController { ); this._context.subscriptions.push( vscode.languages.registerCodeLensProvider( - { language: 'mongodb' }, + { language: 'javascript' }, this._activeConnectionCodeLensProvider ) ); @@ -432,10 +432,11 @@ export default class EditorsController { ); this._context.subscriptions.push( vscode.languages.registerCodeActionsProvider( - 'mongodb', - this._codeActionProvider, + 'javascript', + this._playgroundSelectedCodeActionProvider, { - providedCodeActionKinds: CodeActionProvider.providedCodeActionKinds, + providedCodeActionKinds: + PlaygroundSelectedCodeActionProvider.providedCodeActionKinds, } ) ); diff --git a/src/editors/playgroundController.ts b/src/editors/playgroundController.ts index e4149303a..5daa5939c 100644 --- a/src/editors/playgroundController.ts +++ b/src/editors/playgroundController.ts @@ -1,9 +1,11 @@ import * as vscode from 'vscode'; +import path from 'path'; import { OutputChannel, ProgressLocation, TextEditor } from 'vscode'; import vm from 'vm'; +import * as os from 'os'; import ActiveConnectionCodeLensProvider from './activeConnectionCodeLensProvider'; -import CodeActionProvider from './codeActionProvider'; +import PlaygroundSelectedCodeActionProvider from './playgroundSelectedCodeActionProvider'; import ConnectionController, { DataServiceEventTypes, } from '../connectionController'; @@ -35,6 +37,7 @@ import playgroundSearchTemplate from '../templates/playgroundSearchTemplate'; import playgroundTemplate from '../templates/playgroundTemplate'; import { StatusView } from '../views'; import TelemetryService from '../telemetry/telemetryService'; +import { isPlayground } from '../utils/playground'; const log = createLogger('playground controller'); const transpiler = require('bson-transpilers'); @@ -99,11 +102,11 @@ export default class PlaygroundController { _languageServerController: LanguageServerController; _selectedText?: string; _exportToLanguageCodeLensProvider: ExportToLanguageCodeLensProvider; - _codeActionProvider: CodeActionProvider; + _playgroundSelectedCodeActionProvider: PlaygroundSelectedCodeActionProvider; + _telemetryService: TelemetryService; _isPartialRun = false; - private _telemetryService: TelemetryService; private _activeConnectionCodeLensProvider: ActiveConnectionCodeLensProvider; private _outputChannel: OutputChannel; private _playgroundResultViewColumn?: vscode.ViewColumn; @@ -122,10 +125,11 @@ export default class PlaygroundController { playgroundResultViewProvider: PlaygroundResultProvider, activeConnectionCodeLensProvider: ActiveConnectionCodeLensProvider, exportToLanguageCodeLensProvider: ExportToLanguageCodeLensProvider, - codeActionProvider: CodeActionProvider, + codeActionProvider: PlaygroundSelectedCodeActionProvider, explorerController: ExplorerController ) { this._connectionController = connectionController; + this._activeTextEditor = vscode.window.activeTextEditor; this._languageServerController = languageServerController; this._telemetryService = telemetryService; this._statusView = statusView; @@ -134,7 +138,7 @@ export default class PlaygroundController { vscode.window.createOutputChannel('Playground output'); this._activeConnectionCodeLensProvider = activeConnectionCodeLensProvider; this._exportToLanguageCodeLensProvider = exportToLanguageCodeLensProvider; - this._codeActionProvider = codeActionProvider; + this._playgroundSelectedCodeActionProvider = codeActionProvider; this._explorerController = explorerController; this._connectionController.addEventListener( @@ -152,18 +156,49 @@ export default class PlaygroundController { this._playgroundResultTextDocument = editor?.document; } + void vscode.commands.executeCommand( + 'setContext', + 'mdb.isPlayground', + isPlayground(editor?.document.uri) + ); + if (editor?.document.languageId !== 'Log') { this._activeTextEditor = editor; + this._activeConnectionCodeLensProvider.setActiveTextEditor( + this._activeTextEditor + ); + this._playgroundSelectedCodeActionProvider.setActiveTextEditor( + this._activeTextEditor + ); log.info('Active editor path', editor?.document.uri?.path); } }; + vscode.workspace.textDocuments.forEach((document) => { + if (isPlayground(document.uri)) { + void vscode.languages.setTextDocumentLanguage(document, 'javascript'); + } + }); + vscode.window.onDidChangeActiveTextEditor(onDidChangeActiveTextEditor); onDidChangeActiveTextEditor(vscode.window.activeTextEditor); + vscode.workspace.onDidOpenTextDocument(async (document) => { + if (isPlayground(document.uri)) { + this._telemetryService.trackPlaygroundLoaded(); + await vscode.languages.setTextDocumentLanguage(document, 'javascript'); + } + }); + + vscode.workspace.onDidSaveTextDocument((document) => { + if (isPlayground(document.uri)) { + this._telemetryService.trackPlaygroundSaved(); + } + }); + vscode.window.onDidChangeTextEditorSelection( async (changeEvent: vscode.TextEditorSelectionChangeEvent) => { - if (changeEvent?.textEditor?.document?.languageId !== 'mongodb') { + if (!isPlayground(changeEvent?.textEditor?.document?.uri)) { return; } @@ -188,7 +223,7 @@ export default class PlaygroundController { selection: sortedSelections[0], }); - this._codeActionProvider.refresh({ + this._playgroundSelectedCodeActionProvider.refresh({ selection: sortedSelections[0], mode, }); @@ -231,11 +266,36 @@ export default class PlaygroundController { content: string | undefined ): Promise { try { - const document = await vscode.workspace.openTextDocument({ - language: 'mongodb', - content, + // The MacOS default folder for saving files is a read-only root (/) directory, + // therefore we explicitly specify the workspace folder path + // or OS home directory if a user has not opened workspaces. + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]; + const filePath = workspaceFolder?.uri.fsPath || os.homedir(); + + const numberUntitledPlaygrounds = vscode.workspace.textDocuments.filter( + (doc) => isPlayground(doc.uri) + ).length; + const fileName = path.join( + filePath, + `playground-${numberUntitledPlaygrounds + 1}.mongodb.js` + ); + + // Does not create a physical file, it only creates a URI from specified component parts. + // An untitled file URI: untitled:/extensionPath/playground-1.mongodb.js + const documentUri = vscode.Uri.from({ + path: fileName, + scheme: 'untitled', }); + // Fill in initial content. + const edit = new vscode.WorkspaceEdit(); + edit.insert(documentUri, new vscode.Position(0, 0), `${content}`); + await vscode.workspace.applyEdit(edit); + + // Actually show the editor. + const document = await vscode.workspace.openTextDocument(documentUri); + + // Focus new text document. await vscode.window.showTextDocument(document); return true; @@ -314,23 +374,8 @@ export default class PlaygroundController { const useDefaultTemplate = !!vscode.workspace .getConfiguration('mdb') .get('useDefaultTemplateForPlayground'); - - try { - const document = await vscode.workspace.openTextDocument({ - language: 'mongodb', - content: useDefaultTemplate ? playgroundTemplate : '', - }); - - await vscode.window.showTextDocument(document); - - return true; - } catch (error) { - void vscode.window.showErrorMessage( - `Unable to create a playground: ${formatError(error).message}` - ); - - return false; - } + const content = useDefaultTemplate ? playgroundTemplate : ''; + return this._createPlaygroundFileWithContent(content); } async _evaluate(codeToEvaluate: string): Promise { @@ -550,7 +595,7 @@ export default class PlaygroundController { runAllPlaygroundBlocks(): Promise { if ( !this._activeTextEditor || - this._activeTextEditor.document.languageId !== 'mongodb' + !isPlayground(this._activeTextEditor.document.uri) ) { void vscode.window.showErrorMessage( "Please open a '.mongodb' playground file before running it." @@ -568,7 +613,7 @@ export default class PlaygroundController { runAllOrSelectedPlaygroundBlocks(): Promise { if ( !this._activeTextEditor || - this._activeTextEditor.document.languageId !== 'mongodb' + !isPlayground(this._activeTextEditor.document.uri) ) { void vscode.window.showErrorMessage( "Please open a '.mongodb' playground file before running it." @@ -623,9 +668,9 @@ export default class PlaygroundController { ...this._exportToLanguageCodeLensProvider._exportToLanguageAddons, textFromEditor: this._getAllText(), selectedText: this._selectedText, - selection: this._codeActionProvider.selection, + selection: this._playgroundSelectedCodeActionProvider.selection, language, - mode: this._codeActionProvider.mode, + mode: this._playgroundSelectedCodeActionProvider.mode, }); return this._transpile(); @@ -676,9 +721,15 @@ export default class PlaygroundController { }, }; - if (this._codeActionProvider.mode === ExportToLanguageMode.AGGREGATION) { + if ( + this._playgroundSelectedCodeActionProvider.mode === + ExportToLanguageMode.AGGREGATION + ) { toCompile.aggregation = selectedText; - } else if (this._codeActionProvider.mode === ExportToLanguageMode.QUERY) { + } else if ( + this._playgroundSelectedCodeActionProvider.mode === + ExportToLanguageMode.QUERY + ) { toCompile.filter = selectedText; } @@ -734,7 +785,10 @@ export default class PlaygroundController { log.info(`Export to ${language} language result`, this._playgroundResult); /* eslint-disable camelcase */ - if (this._codeActionProvider.mode === ExportToLanguageMode.AGGREGATION) { + if ( + this._playgroundSelectedCodeActionProvider.mode === + ExportToLanguageMode.AGGREGATION + ) { const aggExportedProps = { language, num_stages: selectedText @@ -746,7 +800,10 @@ export default class PlaygroundController { }; this._telemetryService.trackAggregationExported(aggExportedProps); - } else if (this._codeActionProvider.mode === ExportToLanguageMode.QUERY) { + } else if ( + this._playgroundSelectedCodeActionProvider.mode === + ExportToLanguageMode.QUERY + ) { const queryExportedProps = { language, with_import_statements: importStatements, diff --git a/src/editors/codeActionProvider.ts b/src/editors/playgroundSelectedCodeActionProvider.ts similarity index 85% rename from src/editors/codeActionProvider.ts rename to src/editors/playgroundSelectedCodeActionProvider.ts index 453339f64..ec412b3b9 100644 --- a/src/editors/codeActionProvider.ts +++ b/src/editors/playgroundSelectedCodeActionProvider.ts @@ -1,17 +1,23 @@ import * as vscode from 'vscode'; +import { TextEditor } from 'vscode'; import EXTENSION_COMMANDS from '../commands'; import { ExportToLanguageMode } from '../types/playgroundType'; +import { isPlayground } from '../utils/playground'; -export default class CodeActionProvider implements vscode.CodeActionProvider { +export default class PlaygroundSelectedCodeActionProvider + implements vscode.CodeActionProvider +{ _onDidChangeCodeCodeAction: vscode.EventEmitter = new vscode.EventEmitter(); selection?: vscode.Selection; mode?: ExportToLanguageMode; + activeTextEditor?: TextEditor; static readonly providedCodeActionKinds = [vscode.CodeActionKind.QuickFix]; constructor() { + this.activeTextEditor = vscode.window.activeTextEditor; vscode.workspace.onDidChangeConfiguration(() => { this._onDidChangeCodeCodeAction.fire(); }); @@ -20,6 +26,11 @@ export default class CodeActionProvider implements vscode.CodeActionProvider { readonly onDidChangeCodeLenses: vscode.Event = this._onDidChangeCodeCodeAction.event; + setActiveTextEditor(activeTextEditor?: TextEditor) { + this.activeTextEditor = activeTextEditor; + this._onDidChangeCodeCodeAction.fire(); + } + refresh({ selection, mode, @@ -32,8 +43,12 @@ export default class CodeActionProvider implements vscode.CodeActionProvider { this._onDidChangeCodeCodeAction.fire(); } + isPlayground(): boolean { + return isPlayground(this.activeTextEditor?.document.uri); + } + provideCodeActions(): vscode.CodeAction[] | undefined { - if (!this.selection) { + if (!this.selection || !this.isPlayground()) { return; } diff --git a/src/explorer/playgroundsTree.ts b/src/explorer/playgroundsTree.ts index 09e3fb18c..3386e1dcf 100644 --- a/src/explorer/playgroundsTree.ts +++ b/src/explorer/playgroundsTree.ts @@ -1,57 +1,13 @@ import * as vscode from 'vscode'; -import * as fs from 'fs'; -import * as path from 'path'; import PlaygroundsTreeHeader from './playgroundsTreeHeader'; import { PLAYGROUND_ITEM } from './playgroundsTreeItem'; import { createLogger } from '../logging'; import PlaygroundsTreeItem from './playgroundsTreeItem'; import EXTENSION_COMMANDS from '../commands'; +import { getPlaygrounds } from '../utils/playground'; -const micromatch = require('micromatch'); const log = createLogger('playgrounds tree controller'); -export class FileStat implements vscode.FileStat { - constructor(private fsStat: fs.Stats) {} - - get type(): vscode.FileType { - if (this.fsStat.isFile()) { - return vscode.FileType.File; - } - if (this.fsStat.isDirectory()) { - return vscode.FileType.Directory; - } - if (this.fsStat.isSymbolicLink()) { - return vscode.FileType.SymbolicLink; - } - - return vscode.FileType.Unknown; - } - - get isFile(): boolean | undefined { - return this.fsStat.isFile(); - } - - get isDirectory(): boolean | undefined { - return this.fsStat.isDirectory(); - } - - get isSymbolicLink(): boolean | undefined { - return this.fsStat.isSymbolicLink(); - } - - get size(): number { - return this.fsStat.size; - } - - get ctime(): number { - return this.fsStat.ctime.getTime(); - } - - get mtime(): number { - return this.fsStat.mtime.getTime(); - } -} - export default class PlaygroundsTree implements vscode.TreeDataProvider { @@ -144,54 +100,23 @@ export default class PlaygroundsTree return element; } - private async getFileNames(filePath: string): Promise { - return await fs.promises.readdir(filePath); - } - - private async stat(filePath: string): Promise { - return await fs.promises.stat(filePath); - } - - private async getStat(filePath: string): Promise { - return new FileStat(await this.stat(filePath)); - } - - public async readDirectory(uri: vscode.Uri): Promise { - const fileNames = await this.getFileNames(uri.fsPath); - - for (let i = 0; i < fileNames.length; i++) { - const fileName = fileNames[i]; - - try { - const stat = await this.getStat(path.join(uri.fsPath, fileName)); - const fileUri = vscode.Uri.file(path.join(uri.fsPath, fileName)); - const fileNameParts = fileName.split('.'); - - if ( - stat.type === vscode.FileType.File && - fileNameParts.length > 1 && - fileNameParts.pop() === 'mongodb' - ) { - this._playgroundsTreeItems[fileUri.fsPath] = new PlaygroundsTreeItem( - fileName, - fileUri.fsPath - ); - } else if ( - stat.type === vscode.FileType.Directory && - !micromatch.isMatch(fileName, this.excludeFromPlaygroundsSearch) - ) { - await this.readDirectory(fileUri); - } - } catch (error) { - /* */ - } - } - } + public async getPlaygrounds(fsPath: string): Promise { + const excludeFromPlaygroundsSearch: string[] = + (await vscode.workspace + .getConfiguration('mdb') + .get('excludeFromPlaygroundsSearch')) || []; - public async getPlaygrounds(folderUri: vscode.Uri): Promise { - this._playgroundsTreeItems = {}; + const playgrounds = await getPlaygrounds({ + fsPath, + excludeFromPlaygroundsSearch, + }); - await this.readDirectory(folderUri); + this._playgroundsTreeItems = Object.fromEntries( + playgrounds.map((playground) => [ + playground.path, + new PlaygroundsTreeItem(playground.name, playground.path), + ]) + ); return this._playgroundsTreeItems; } @@ -209,7 +134,7 @@ export default class PlaygroundsTree ); for (const folder of workspaceFolders) { - const playgrounds = await this.getPlaygrounds(folder.uri); + const playgrounds = await this.getPlaygrounds(folder.uri.fsPath); if (Object.keys(playgrounds).length > 0) { this._playgroundsTreeHeaders.push( diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index c079fa0b2..749d7697b 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -61,8 +61,8 @@ export default class LanguageServerController { const clientOptions: LanguageClientOptions = { // Register the server for mongodb documents documentSelector: [ - { scheme: 'untitled', language: 'mongodb' }, - { scheme: 'file', language: 'mongodb' }, + { scheme: 'untitled', language: 'javascript' }, + { scheme: 'file', language: 'javascript' }, ], synchronize: { // Notify the server about file changes in the workspace diff --git a/src/mdbExtensionController.ts b/src/mdbExtensionController.ts index a65d98cc4..0f9c2d2ba 100644 --- a/src/mdbExtensionController.ts +++ b/src/mdbExtensionController.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import ActiveConnectionCodeLensProvider from './editors/activeConnectionCodeLensProvider'; -import CodeActionProvider from './editors/codeActionProvider'; +import PlaygroundSelectedCodeActionProvider from './editors/playgroundSelectedCodeActionProvider'; import ConnectionController from './connectionController'; import ConnectionTreeItem from './explorer/connectionTreeItem'; import { createLogger } from './logging'; @@ -44,7 +44,7 @@ const log = createLogger('commands'); // This class is the top-level controller for our extension. // Commands which the extensions handles are defined in the function `activate`. export default class MDBExtensionController implements vscode.Disposable { - _codeActionProvider: CodeActionProvider; + _playgroundSelectedCodeActionProvider: PlaygroundSelectedCodeActionProvider; _connectionController: ConnectionController; _context: vscode.ExtensionContext; _editorsController: EditorsController; @@ -96,7 +96,8 @@ export default class MDBExtensionController implements vscode.Disposable { new ActiveConnectionCodeLensProvider(this._connectionController); this._exportToLanguageCodeLensProvider = new ExportToLanguageCodeLensProvider(); - this._codeActionProvider = new CodeActionProvider(); + this._playgroundSelectedCodeActionProvider = + new PlaygroundSelectedCodeActionProvider(); this._playgroundController = new PlaygroundController( this._connectionController, this._languageServerController, @@ -105,7 +106,7 @@ export default class MDBExtensionController implements vscode.Disposable { this._playgroundResultViewProvider, this._activeConnectionCodeLensProvider, this._exportToLanguageCodeLensProvider, - this._codeActionProvider, + this._playgroundSelectedCodeActionProvider, this._explorerController ); this._editorsController = new EditorsController( @@ -117,7 +118,7 @@ export default class MDBExtensionController implements vscode.Disposable { this._playgroundResultViewProvider, this._activeConnectionCodeLensProvider, this._exportToLanguageCodeLensProvider, - this._codeActionProvider, + this._playgroundSelectedCodeActionProvider, this._editDocumentCodeLensProvider ); this._webviewController = new WebviewController( diff --git a/src/telemetry/telemetryService.ts b/src/telemetry/telemetryService.ts index 0890c3714..0d2640fb6 100644 --- a/src/telemetry/telemetryService.ts +++ b/src/telemetry/telemetryService.ts @@ -8,10 +8,8 @@ import SegmentAnalytics from 'analytics-node'; import { ConnectionTypes } from '../connectionController'; import { createLogger } from '../logging'; import { DocumentSource } from '../documentSource'; -import { - getConnectionTelemetryProperties, - NewConnectionTelemetryEventProperties, -} from './connectionTelemetry'; +import { getConnectionTelemetryProperties } from './connectionTelemetry'; +import type { NewConnectionTelemetryEventProperties } from './connectionTelemetry'; import type { ShellExecuteAllResult } from '../types/playgroundType'; import { StorageController } from '../storage'; @@ -104,22 +102,6 @@ export default class TelemetryService { this._segmentUserId = userId; this._segmentAnonymousId = anonymousId; this._segmentKey = this._readSegmentKey(); - - vscode.workspace.onDidOpenTextDocument((document) => { - if ( - document && - document.languageId === 'mongodb' && - document.uri.scheme === 'file' - ) { - this.trackPlaygroundLoaded(); - } - }); - - vscode.workspace.onDidSaveTextDocument((document) => { - if (document && document.languageId === 'mongodb') { - this.trackPlaygroundSaved(); - } - }); } private _readSegmentKey(): string | undefined { diff --git a/src/templates/playgroundCloneDocumentTemplate.ts b/src/templates/playgroundCloneDocumentTemplate.ts index b31770f48..bf34936b2 100644 --- a/src/templates/playgroundCloneDocumentTemplate.ts +++ b/src/templates/playgroundCloneDocumentTemplate.ts @@ -1,4 +1,5 @@ -const template = `// MongoDB Playground +const template = `/* global use, db */ +// MongoDB Playground // Use Ctrl+Space inside a snippet or a string literal to trigger completions. // The current database to use. diff --git a/src/templates/playgroundCreateCollectionTemplate.ts b/src/templates/playgroundCreateCollectionTemplate.ts index b6fa0db3e..a24eba944 100644 --- a/src/templates/playgroundCreateCollectionTemplate.ts +++ b/src/templates/playgroundCreateCollectionTemplate.ts @@ -1,4 +1,5 @@ -const template = `// MongoDB Playground +const template = `/* global use, db */ +// MongoDB Playground // Use Ctrl+Space inside a snippet or a string literal to trigger completions. const database = 'NEW_DATABASE_NAME'; diff --git a/src/templates/playgroundCreateIndexTemplate.ts b/src/templates/playgroundCreateIndexTemplate.ts index 0a88018ae..b21e1b533 100644 --- a/src/templates/playgroundCreateIndexTemplate.ts +++ b/src/templates/playgroundCreateIndexTemplate.ts @@ -1,4 +1,5 @@ -const template = `// MongoDB Playground +const template = `/* global use, db */ +// MongoDB Playground // Use Ctrl+Space inside a snippet or a string literal to trigger completions. // The current database to use. diff --git a/src/templates/playgroundSearchTemplate.ts b/src/templates/playgroundSearchTemplate.ts index 81d3cd404..be3ddb573 100644 --- a/src/templates/playgroundSearchTemplate.ts +++ b/src/templates/playgroundSearchTemplate.ts @@ -1,4 +1,5 @@ -const template = `// MongoDB Playground +const template = `/* global use, db */ +// MongoDB Playground // Use Ctrl+Space inside a snippet or a string literal to trigger completions. // The current database to use. diff --git a/src/templates/playgroundTemplate.ts b/src/templates/playgroundTemplate.ts index 0d3f9c151..c65696d4c 100644 --- a/src/templates/playgroundTemplate.ts +++ b/src/templates/playgroundTemplate.ts @@ -1,4 +1,5 @@ -const template = `// MongoDB Playground +const template = `/* global use, db */ +// MongoDB Playground // To disable this template go to Settings | MongoDB | Use Default Template For Playground. // Make sure you are connected to enable completions and to be able to run a playground. // Use Ctrl+Space inside a snippet or a string literal to trigger completions. diff --git a/src/test/runTest.ts b/src/test/runTest.ts index 7e67dc4a9..1b426f0b6 100644 --- a/src/test/runTest.ts +++ b/src/test/runTest.ts @@ -10,8 +10,7 @@ async function main(): Promise { // Passed to `--extensionDevelopmentPath` const extensionDevelopmentPath = path.join(__dirname, '../../'); - // The path to test runner - // Passed to --extensionTestsPath + // The path to test runner pased to --extensionTestsPath const extensionTestsPath = path.join(__dirname, './suite/index'); // This is the workspace we open in our tests. diff --git a/src/test/suite/editors/activeConnectionCodeLensProvider.test.ts b/src/test/suite/editors/activeConnectionCodeLensProvider.test.ts new file mode 100644 index 000000000..4ad2772d9 --- /dev/null +++ b/src/test/suite/editors/activeConnectionCodeLensProvider.test.ts @@ -0,0 +1,207 @@ +import * as vscode from 'vscode'; +import { beforeEach, afterEach } from 'mocha'; +import chai from 'chai'; +import sinon from 'sinon'; +import type { DataService } from 'mongodb-data-service'; + +import ActiveConnectionCodeLensProvider from '../../../editors/activeConnectionCodeLensProvider'; +import ConnectionController from '../../../connectionController'; +import { StatusView } from '../../../views'; +import { StorageController } from '../../../storage'; +import { TestExtensionContext } from '../stubs'; +import TelemetryService from '../../../telemetry/telemetryService'; + +const expect = chai.expect; + +suite('Active Connection CodeLens Provider Test Suite', () => { + const mockExtensionContext = new TestExtensionContext(); + const mockStorageController = new StorageController(mockExtensionContext); + const testTelemetryService = new TelemetryService( + mockStorageController, + mockExtensionContext + ); + const testStatusView = new StatusView(mockExtensionContext); + + suite('the MongoDB playground in JS', () => { + suite('user is not connected', () => { + const testConnectionController = new ConnectionController( + testStatusView, + mockStorageController, + testTelemetryService + ); + const testCodeLensProvider = new ActiveConnectionCodeLensProvider( + testConnectionController + ); + const mockShowQuickPick = sinon.fake(); + + beforeEach(() => { + testCodeLensProvider.setActiveTextEditor( + vscode.window.activeTextEditor + ); + sinon.replace(vscode.window, 'showQuickPick', mockShowQuickPick); + const mockIsPlayground = sinon.fake.returns(true); + sinon.replace(testCodeLensProvider, 'isPlayground', mockIsPlayground); + }); + + afterEach(() => { + sinon.restore(); + }); + + test('show disconnected message in code lenses', () => { + const codeLens = testCodeLensProvider.provideCodeLenses(); + + expect(codeLens).to.be.an('array'); + expect(codeLens.length).to.be.equal(1); + expect(codeLens[0].command?.title).to.be.equal( + 'Disconnected. Click here to connect.' + ); + expect(codeLens[0].range.start.line).to.be.equal(0); + expect(codeLens[0].range.end.line).to.be.equal(0); + }); + }); + + suite('user is connected', () => { + const testConnectionController = new ConnectionController( + testStatusView, + mockStorageController, + testTelemetryService + ); + const testCodeLensProvider = new ActiveConnectionCodeLensProvider( + testConnectionController + ); + const findStub = sinon.stub(); + findStub.resolves([ + { + field: 'Text message', + }, + ]); + const instanceStub = sinon.stub(); + instanceStub.resolves({ + dataLake: {}, + build: {}, + genuineMongoDB: {}, + host: {}, + } as unknown as Awaited>); + const mockActiveDataService = { + find: findStub, + instance: instanceStub, + } as Pick as unknown as DataService; + + testConnectionController.setActiveDataService(mockActiveDataService); + + beforeEach(() => { + testCodeLensProvider.setActiveTextEditor( + vscode.window.activeTextEditor + ); + sinon.replace( + testConnectionController, + 'getActiveConnectionName', + sinon.fake.returns('fakeName') + ); + const mockIsPlayground = sinon.fake.returns(true); + sinon.replace(testCodeLensProvider, 'isPlayground', mockIsPlayground); + }); + + afterEach(() => { + sinon.restore(); + }); + + test('show active connection in code lenses', () => { + const codeLens = testCodeLensProvider.provideCodeLenses(); + + expect(codeLens).to.be.an('array'); + expect(codeLens.length).to.be.equal(1); + expect(codeLens[0].command?.title).to.be.equal( + 'Currently connected to fakeName. Click here to change connection.' + ); + expect(codeLens[0].range.start.line).to.be.equal(0); + expect(codeLens[0].range.end.line).to.be.equal(0); + expect(codeLens[0].command?.command).to.be.equal( + 'mdb.changeActiveConnection' + ); + }); + }); + }); + + suite('the regular JS file', () => { + suite('user is not connected', () => { + const testConnectionController = new ConnectionController( + testStatusView, + mockStorageController, + testTelemetryService + ); + const testCodeLensProvider = new ActiveConnectionCodeLensProvider( + testConnectionController + ); + const mockShowQuickPick = sinon.fake(); + + beforeEach(() => { + sinon.replace(vscode.window, 'showQuickPick', mockShowQuickPick); + const mockIsPlayground = sinon.fake.returns(false); + sinon.replace(testCodeLensProvider, 'isPlayground', mockIsPlayground); + }); + + afterEach(() => { + sinon.restore(); + }); + + test('show not show the active connection code lenses', () => { + const codeLens = testCodeLensProvider.provideCodeLenses(); + + expect(codeLens).to.be.an('array'); + expect(codeLens.length).to.be.equal(0); + }); + }); + + suite('user is connected', () => { + const testConnectionController = new ConnectionController( + testStatusView, + mockStorageController, + testTelemetryService + ); + const testCodeLensProvider = new ActiveConnectionCodeLensProvider( + testConnectionController + ); + + const findStub = sinon.stub(); + findStub.resolves([ + { + field: 'Text message', + }, + ]); + const instanceStub = sinon.stub(); + instanceStub.resolves({ + dataLake: {}, + build: {}, + genuineMongoDB: {}, + host: {}, + } as unknown as Awaited>); + const mockActiveDataService = { + find: findStub, + instance: instanceStub, + } as Pick as unknown as DataService; + testConnectionController.setActiveDataService(mockActiveDataService); + + beforeEach(() => { + sinon.replace( + testConnectionController, + 'getActiveConnectionName', + sinon.fake.returns('fakeName') + ); + const mockIsPlayground = sinon.fake.returns(false); + sinon.replace(testCodeLensProvider, 'isPlayground', mockIsPlayground); + }); + + afterEach(() => { + sinon.restore(); + }); + + test('show not show the active connection code lensess', () => { + const codeLens = testCodeLensProvider.provideCodeLenses(); + + expect(codeLens).to.be.an('array'); + expect(codeLens.length).to.be.equal(0); + }); + }); + }); +}); diff --git a/src/test/suite/editors/activeDBCodeLensProvider.test.ts b/src/test/suite/editors/activeDBCodeLensProvider.test.ts deleted file mode 100644 index 463e1b242..000000000 --- a/src/test/suite/editors/activeDBCodeLensProvider.test.ts +++ /dev/null @@ -1,113 +0,0 @@ -import * as vscode from 'vscode'; -import { beforeEach, afterEach } from 'mocha'; -import chai from 'chai'; -import sinon from 'sinon'; -import type { DataService } from 'mongodb-data-service'; - -import ActiveDBCodeLensProvider from '../../../editors/activeConnectionCodeLensProvider'; -import ConnectionController from '../../../connectionController'; -import { StatusView } from '../../../views'; -import { StorageController } from '../../../storage'; -import { TestExtensionContext } from '../stubs'; -import TelemetryService from '../../../telemetry/telemetryService'; - -const expect = chai.expect; - -suite('Active DB CodeLens Provider Test Suite', () => { - const mockExtensionContext = new TestExtensionContext(); - const mockStorageController = new StorageController(mockExtensionContext); - const testTelemetryService = new TelemetryService( - mockStorageController, - mockExtensionContext - ); - const testStatusView = new StatusView(mockExtensionContext); - - suite('user is not connected', () => { - const testConnectionController = new ConnectionController( - testStatusView, - mockStorageController, - testTelemetryService - ); - const testCodeLensProvider = new ActiveDBCodeLensProvider( - testConnectionController - ); - const mockShowQuickPick = sinon.fake(); - - beforeEach(() => { - sinon.replace(vscode.window, 'showQuickPick', mockShowQuickPick); - }); - - afterEach(() => { - sinon.restore(); - }); - - test('show disconnected message in code lenses', () => { - const codeLens = testCodeLensProvider.provideCodeLenses(); - - expect(codeLens).to.be.an('array'); - expect(codeLens.length).to.be.equal(1); - expect(codeLens[0].command?.title).to.be.equal( - 'Disconnected. Click here to connect.' - ); - expect(codeLens[0].range.start.line).to.be.equal(0); - expect(codeLens[0].range.end.line).to.be.equal(0); - }); - }); - - suite('user is connected', () => { - const testConnectionController = new ConnectionController( - testStatusView, - mockStorageController, - testTelemetryService - ); - const testCodeLensProvider = new ActiveDBCodeLensProvider( - testConnectionController - ); - - const findStub = sinon.stub(); - findStub.resolves([ - { - field: 'Text message', - }, - ]); - const instanceStub = sinon.stub(); - instanceStub.resolves({ - dataLake: {}, - build: {}, - genuineMongoDB: {}, - host: {}, - } as unknown as Awaited>); - const mockActiveDataService = { - find: findStub, - instance: instanceStub, - } as Pick as unknown as DataService; - testConnectionController.setActiveDataService(mockActiveDataService); - - beforeEach(() => { - sinon.replace( - testConnectionController, - 'getActiveConnectionName', - sinon.fake.returns('fakeName') - ); - }); - - afterEach(() => { - sinon.restore(); - }); - - test('show active connection in code lenses', () => { - const codeLens = testCodeLensProvider.provideCodeLenses(); - - expect(codeLens).to.be.an('array'); - expect(codeLens.length).to.be.equal(1); - expect(codeLens[0].command?.title).to.be.equal( - 'Currently connected to fakeName. Click here to change connection.' - ); - expect(codeLens[0].range.start.line).to.be.equal(0); - expect(codeLens[0].range.end.line).to.be.equal(0); - expect(codeLens[0].command?.command).to.be.equal( - 'mdb.changeActiveConnection' - ); - }); - }); -}); diff --git a/src/test/suite/editors/codeActionProvider.test.ts b/src/test/suite/editors/codeActionProvider.test.ts deleted file mode 100644 index 43cbfbe8e..000000000 --- a/src/test/suite/editors/codeActionProvider.test.ts +++ /dev/null @@ -1,478 +0,0 @@ -import * as vscode from 'vscode'; -import { beforeEach, afterEach } from 'mocha'; -import chai from 'chai'; -import sinon from 'sinon'; - -import ActiveDBCodeLensProvider from '../../../editors/activeConnectionCodeLensProvider'; -import ExportToLanguageCodeLensProvider from '../../../editors/exportToLanguageCodeLensProvider'; -import CodeActionProvider from '../../../editors/codeActionProvider'; -import { ExplorerController } from '../../../explorer'; -import { LanguageServerController } from '../../../language'; -import { mdbTestExtension } from '../stubbableMdbExtension'; -import { PlaygroundController } from '../../../editors'; -import { - PlaygroundResult, - ExportToLanguageMode, -} from '../../../types/playgroundType'; -import { TEST_DATABASE_URI } from '../dbTestHelper'; -import { TestExtensionContext } from '../stubs'; - -const expect = chai.expect; - -suite('Code Action Provider Test Suite', function () { - this.timeout(5000); - - const testExtensionContext = new TestExtensionContext(); - testExtensionContext.extensionPath = '../../'; - - beforeEach(async () => { - sinon.replace( - mdbTestExtension.testExtensionController, - '_languageServerController', - new LanguageServerController(testExtensionContext) - ); - sinon.replace( - vscode.window, - 'showInformationMessage', - sinon.fake.resolves(true) - ); - - await mdbTestExtension.testExtensionController._connectionController.addNewConnectionStringAndConnect( - TEST_DATABASE_URI - ); - - const testActiveDBCodeLensProvider = new ActiveDBCodeLensProvider( - mdbTestExtension.testExtensionController._connectionController - ); - const testExportToLanguageCodeLensProvider = - new ExportToLanguageCodeLensProvider(); - const testCodeActionProvider = new CodeActionProvider(); - const testExplorerController = new ExplorerController( - mdbTestExtension.testExtensionController._connectionController - ); - - mdbTestExtension.testExtensionController._playgroundController = - new PlaygroundController( - mdbTestExtension.testExtensionController._connectionController, - mdbTestExtension.testExtensionController._languageServerController, - mdbTestExtension.testExtensionController._telemetryService, - mdbTestExtension.testExtensionController._statusView, - mdbTestExtension.testExtensionController._playgroundResultViewProvider, - testActiveDBCodeLensProvider, - testExportToLanguageCodeLensProvider, - testCodeActionProvider, - testExplorerController - ); - - const mockOpenPlaygroundResult: any = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._playgroundController, - '_openPlaygroundResult', - mockOpenPlaygroundResult - ); - - await vscode.workspace - .getConfiguration('mdb') - .update('confirmRunAll', false); - - await mdbTestExtension.testExtensionController._languageServerController.startLanguageServer(); - await mdbTestExtension.testExtensionController._playgroundController._connectToServiceProvider(); - }); - - afterEach(async () => { - await vscode.workspace - .getConfiguration('mdb') - .update('confirmRunAll', true); - await mdbTestExtension.testExtensionController._connectionController.disconnect(); - mdbTestExtension.testExtensionController._connectionController.clearAllConnections(); - sinon.restore(); - }); - - test('returns undefined when text is not selected', () => { - const testCodeActionProvider = new CodeActionProvider(); - const codeActions = testCodeActionProvider.provideCodeActions(); - - expect(codeActions).to.be.undefined; - }); - - test('returns a run selected playground blocks action', async () => { - mdbTestExtension.testExtensionController._playgroundController._selectedText = - '123'; - - const selection = { - start: { line: 0, character: 0 }, - end: { line: 0, character: 4 }, - } as vscode.Selection; - const testCodeActionProvider = new CodeActionProvider(); - - testCodeActionProvider.refresh({ - selection, - mode: ExportToLanguageMode.OTHER, - }); - - const codeActions = testCodeActionProvider.provideCodeActions(); - - expect(codeActions).to.exist; - - if (codeActions) { - expect(codeActions.length).to.be.equal(1); - const actionCommand = codeActions[0].command; - - if (actionCommand) { - expect(actionCommand.command).to.be.equal( - 'mdb.runSelectedPlaygroundBlocks' - ); - expect(actionCommand.title).to.be.equal( - 'Run selected playground blocks' - ); - - await vscode.commands.executeCommand(actionCommand.command); - - const expectedResult = { - namespace: null, - type: 'number', - content: 123, - language: 'plaintext', - }; - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - expect( - mdbTestExtension.testExtensionController._playgroundController - ._isPartialRun - ).to.be.equal(true); - } - } - }); - - test('returns an export to java action with whitespaces around objects', () => { - const textFromEditor = ' { name: "Alena Khineika" } '; - const selection = { - start: { line: 0, character: 2 }, - end: { line: 0, character: 27 }, - } as vscode.Selection; - const mode = ExportToLanguageMode.QUERY; - const activeTextEditor = { - document: { getText: () => textFromEditor }, - } as vscode.TextEditor; - - mdbTestExtension.testExtensionController._playgroundController._selectedText = - textFromEditor; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.selection = - selection; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.mode = - mode; - mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = - activeTextEditor; - - const testCodeActionProvider = new CodeActionProvider(); - testCodeActionProvider.refresh({ selection, mode }); - - const codeActions = testCodeActionProvider.provideCodeActions(); - - expect(codeActions).to.exist; - - if (codeActions) { - expect(codeActions.length).to.be.equal(6); - const actionCommand = codeActions[2].command; - - if (actionCommand) { - expect(actionCommand.command).to.be.equal('mdb.exportToJava'); - expect(actionCommand.title).to.be.equal('Export To Java'); - } - } - }); - - test('exports to java and includes builders', async () => { - const textFromEditor = "{ name: '22' }"; - const selection = { - start: { line: 0, character: 0 }, - end: { line: 0, character: 14 }, - } as vscode.Selection; - const mode = ExportToLanguageMode.QUERY; - const activeTextEditor = { - document: { getText: () => textFromEditor }, - } as vscode.TextEditor; - - mdbTestExtension.testExtensionController._playgroundController._selectedText = - textFromEditor; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.selection = - selection; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.mode = - mode; - mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = - activeTextEditor; - - const testCodeActionProvider = new CodeActionProvider(); - testCodeActionProvider.refresh({ selection, mode }); - - const codeActions = testCodeActionProvider.provideCodeActions(); - - expect(codeActions).to.exist; - - if (codeActions) { - expect(codeActions.length).to.be.equal(6); - const actionCommand = codeActions[2].command; - - if (actionCommand) { - expect(actionCommand.command).to.be.equal('mdb.exportToJava'); - expect(actionCommand.title).to.be.equal('Export To Java'); - - await vscode.commands.executeCommand(actionCommand.command); - - const expectedResult = { - namespace: 'DATABASE_NAME.COLLECTION_NAME', - type: null, - content: 'new Document("name", "22")', - language: 'java', - }; - - const codeLenses = - mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); - expect(codeLenses.length).to.be.equal(3); - - // Only java queries supports builders. - await vscode.commands.executeCommand( - 'mdb.changeExportToLanguageAddons', - { - ...mdbTestExtension.testExtensionController._playgroundController - ._exportToLanguageCodeLensProvider._exportToLanguageAddons, - builders: true, - } - ); - - expectedResult.content = 'eq("name", "22")'; - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - } - } - }); - - test('exports to csharp and includes import statements', async () => { - const textFromEditor = "{ name: '22' }"; - const selection = { - start: { line: 0, character: 0 }, - end: { line: 0, character: 14 }, - } as vscode.Selection; - const mode = ExportToLanguageMode.QUERY; - const activeTextEditor = { - document: { getText: () => textFromEditor }, - } as vscode.TextEditor; - - mdbTestExtension.testExtensionController._playgroundController._selectedText = - textFromEditor; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.selection = - selection; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.mode = - mode; - mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = - activeTextEditor; - - const testCodeActionProvider = new CodeActionProvider(); - - testCodeActionProvider.refresh({ selection, mode }); - - const codeActions = testCodeActionProvider.provideCodeActions(); - - expect(codeActions).to.exist; - - if (codeActions) { - expect(codeActions.length).to.be.equal(6); - const actionCommand = codeActions[3].command; - - if (actionCommand) { - expect(actionCommand.command).to.be.equal('mdb.exportToCsharp'); - expect(actionCommand.title).to.be.equal('Export To C#'); - - await vscode.commands.executeCommand(actionCommand.command); - - const expectedResult = { - namespace: 'DATABASE_NAME.COLLECTION_NAME', - type: null, - content: 'new BsonDocument("name", "22")', - language: 'csharp', - }; - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - - const codeLenses = - mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); - expect(codeLenses.length).to.be.equal(1); // Csharp does not support driver syntax. - - await vscode.commands.executeCommand( - 'mdb.changeExportToLanguageAddons', - { - ...mdbTestExtension.testExtensionController._playgroundController - ._exportToLanguageCodeLensProvider._exportToLanguageAddons, - importStatements: true, - } - ); - - expectedResult.content = - 'using MongoDB.Bson;\nusing MongoDB.Driver;\n\nnew BsonDocument("name", "22")'; - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - } - } - }); - - test('exports to python and includes driver syntax', async () => { - const textFromEditor = "use('db'); db.coll.find({ name: '22' })"; - const selection = { - start: { line: 0, character: 24 }, - end: { line: 0, character: 38 }, - } as vscode.Selection; - const mode = ExportToLanguageMode.QUERY; - const activeTextEditor = { - document: { getText: () => textFromEditor }, - } as vscode.TextEditor; - - mdbTestExtension.testExtensionController._playgroundController._selectedText = - "{ name: '22' }"; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.selection = - selection; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.mode = - mode; - mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = - activeTextEditor; - - const testCodeActionProvider = new CodeActionProvider(); - testCodeActionProvider.refresh({ selection, mode }); - - const codeActions = testCodeActionProvider.provideCodeActions(); - - expect(codeActions).to.exist; - - if (codeActions) { - expect(codeActions.length).to.be.equal(6); - const actionCommand = codeActions[1].command; - - if (actionCommand) { - expect(actionCommand.command).to.be.equal('mdb.exportToPython'); - expect(actionCommand.title).to.be.equal('Export To Python 3'); - - await vscode.commands.executeCommand(actionCommand.command); - - let expectedResult: PlaygroundResult = { - namespace: 'DATABASE_NAME.COLLECTION_NAME', - type: null, - content: "{\n 'name': '22'\n}", - language: 'python', - }; - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - - const codeLenses = - mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); - expect(codeLenses.length).to.be.equal(2); - - await vscode.commands.executeCommand( - 'mdb.changeExportToLanguageAddons', - { - ...mdbTestExtension.testExtensionController._playgroundController - ._exportToLanguageCodeLensProvider._exportToLanguageAddons, - driverSyntax: true, - } - ); - - expectedResult = { - namespace: 'db.coll', - type: null, - content: - "# Requires the PyMongo package.\n# https://api.mongodb.com/python/current\n\nclient = MongoClient('mongodb://localhost:27018/?appname=mongodb-vscode+0.0.0-dev.0')\nfilter={\n 'name': '22'\n}\n\nresult = client['db']['coll'].find(\n filter=filter\n)", - language: 'python', - }; - - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - } - } - }); - test('exports to ruby and includes driver syntax', async () => { - const textFromEditor = "use('db'); db.coll.find({ name: '22' })"; - const selection = { - start: { line: 0, character: 24 }, - end: { line: 0, character: 38 }, - } as vscode.Selection; - const mode = ExportToLanguageMode.QUERY; - const activeTextEditor = { - document: { getText: () => textFromEditor }, - } as vscode.TextEditor; - - mdbTestExtension.testExtensionController._playgroundController._selectedText = - "{ name: '22' }"; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.selection = - selection; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.mode = - mode; - mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = - activeTextEditor; - - const testCodeActionProvider = new CodeActionProvider(); - testCodeActionProvider.refresh({ selection, mode }); - - const codeActions = testCodeActionProvider.provideCodeActions(); - - expect(codeActions).to.exist; - - if (codeActions) { - expect(codeActions.length).to.be.equal(6); - const actionCommand = codeActions[5].command; - - if (actionCommand) { - expect(actionCommand.command).to.be.equal('mdb.exportToRuby'); - expect(actionCommand.title).to.be.equal('Export To Ruby'); - - await vscode.commands.executeCommand(actionCommand.command); - - let expectedResult: PlaygroundResult = { - namespace: 'DATABASE_NAME.COLLECTION_NAME', - type: null, - content: "{\n 'name' => '22'\n}", - language: 'ruby', - }; - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - - const codeLenses = - mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); - expect(codeLenses.length).to.be.equal(2); - - await vscode.commands.executeCommand( - 'mdb.changeExportToLanguageAddons', - { - ...mdbTestExtension.testExtensionController._playgroundController - ._exportToLanguageCodeLensProvider._exportToLanguageAddons, - driverSyntax: true, - } - ); - - expectedResult = { - namespace: 'db.coll', - type: null, - content: - "# Requires the MongoDB Ruby Driver\n# https://docs.mongodb.com/ruby-driver/master/\n\nclient = Mongo::Client.new('mongodb://localhost:27018/?appname=mongodb-vscode+0.0.0-dev.0', :database => 'db')\n\nresult = client.database['coll'].find({\n 'name' => '22'\n})", - language: 'ruby', - }; - - expect( - mdbTestExtension.testExtensionController._playgroundController - ._playgroundResult - ).to.be.deep.equal(expectedResult); - } - } - }); -}); diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 760b28e77..26621454c 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -1,11 +1,13 @@ import * as vscode from 'vscode'; import { before, beforeEach, afterEach } from 'mocha'; import chai from 'chai'; -import { DataService } from 'mongodb-data-service'; +import type { DataService } from 'mongodb-data-service'; import sinon from 'sinon'; +import { v4 as uuidv4 } from 'uuid'; +import path from 'path'; import ActiveDBCodeLensProvider from '../../../editors/activeConnectionCodeLensProvider'; -import CodeActionProvider from '../../../editors/codeActionProvider'; +import PlaygroundSelectedCodeActionProvider from '../../../editors/playgroundSelectedCodeActionProvider'; import ConnectionController from '../../../connectionController'; import EditDocumentCodeLensProvider from '../../../editors/editDocumentCodeLensProvider'; import { ExplorerController } from '../../../explorer'; @@ -29,6 +31,7 @@ suite('Playground Controller Test Suite', function () { const mockExtensionContext = new TestExtensionContext(); + // The test extension runner. mockExtensionContext.extensionPath = '../../'; const mockStorageController = new StorageController(mockExtensionContext); @@ -58,7 +61,7 @@ suite('Playground Controller Test Suite', function () { ); const testExportToLanguageCodeLensProvider = new ExportToLanguageCodeLensProvider(); - const testCodeActionProvider = new CodeActionProvider(); + const testCodeActionProvider = new PlaygroundSelectedCodeActionProvider(); const testExplorerController = new ExplorerController( testConnectionController ); @@ -201,12 +204,15 @@ suite('Playground Controller Test Suite', function () { }); suite('playground is open', () => { + const fileName = path.join( + 'nonexistent', + `playground-${uuidv4()}.mongodb.js` + ); + const documentUri = vscode.Uri.from({ path: fileName, scheme: 'untitled' }); const activeTestEditorMock: unknown = { document: { - languageId: 'mongodb', - uri: { - path: 'test', - }, + languageId: 'javascript', + uri: documentUri, getText: () => "use('dbName');", lineAt: sinon.fake.returns({ text: "use('dbName');" }), }, @@ -505,8 +511,10 @@ suite('Playground Controller Test Suite', function () { .resolves(undefined); playgroundControllerTest._selectedText = '{ name: qwerty }'; - playgroundControllerTest._codeActionProvider.selection = selection; - playgroundControllerTest._codeActionProvider.mode = mode; + playgroundControllerTest._playgroundSelectedCodeActionProvider.selection = + selection; + playgroundControllerTest._playgroundSelectedCodeActionProvider.mode = + mode; playgroundControllerTest._activeTextEditor = activeTextEditor; await playgroundControllerTest.exportToLanguage('csharp'); diff --git a/src/test/suite/editors/playgroundSelectedCodeActionProvider.test.ts b/src/test/suite/editors/playgroundSelectedCodeActionProvider.test.ts new file mode 100644 index 000000000..54419a582 --- /dev/null +++ b/src/test/suite/editors/playgroundSelectedCodeActionProvider.test.ts @@ -0,0 +1,512 @@ +import * as vscode from 'vscode'; +import { beforeEach, afterEach } from 'mocha'; +import chai from 'chai'; +import sinon from 'sinon'; + +import ActiveConnectionCodeLensProvider from '../../../editors/activeConnectionCodeLensProvider'; +import ExportToLanguageCodeLensProvider from '../../../editors/exportToLanguageCodeLensProvider'; +import PlaygroundSelectedCodeActionProvider from '../../../editors/playgroundSelectedCodeActionProvider'; +import { ExplorerController } from '../../../explorer'; +import { LanguageServerController } from '../../../language'; +import { mdbTestExtension } from '../stubbableMdbExtension'; +import { PlaygroundController } from '../../../editors'; +import { + PlaygroundResult, + ExportToLanguageMode, +} from '../../../types/playgroundType'; +import { TEST_DATABASE_URI } from '../dbTestHelper'; +import { TestExtensionContext } from '../stubs'; + +const expect = chai.expect; + +suite('Playground Selected CodeAction Provider Test Suite', function () { + this.timeout(5000); + + const mockExtensionContext = new TestExtensionContext(); + + // The test extension runner. + mockExtensionContext.extensionPath = '../../'; + + suite('the MongoDB playground in JS', () => { + const testCodeActionProvider = new PlaygroundSelectedCodeActionProvider(); + + beforeEach(async () => { + sinon.replace( + mdbTestExtension.testExtensionController, + '_languageServerController', + new LanguageServerController(mockExtensionContext) + ); + sinon.replace( + vscode.window, + 'showInformationMessage', + sinon.fake.resolves(true) + ); + + await mdbTestExtension.testExtensionController._connectionController.addNewConnectionStringAndConnect( + TEST_DATABASE_URI + ); + + const activeConnectionCodeLensProvider = + new ActiveConnectionCodeLensProvider( + mdbTestExtension.testExtensionController._connectionController + ); + const testExportToLanguageCodeLensProvider = + new ExportToLanguageCodeLensProvider(); + const testExplorerController = new ExplorerController( + mdbTestExtension.testExtensionController._connectionController + ); + + mdbTestExtension.testExtensionController._playgroundController = + new PlaygroundController( + mdbTestExtension.testExtensionController._connectionController, + mdbTestExtension.testExtensionController._languageServerController, + mdbTestExtension.testExtensionController._telemetryService, + mdbTestExtension.testExtensionController._statusView, + mdbTestExtension.testExtensionController._playgroundResultViewProvider, + activeConnectionCodeLensProvider, + testExportToLanguageCodeLensProvider, + testCodeActionProvider, + testExplorerController + ); + + const mockOpenPlaygroundResult: any = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._playgroundController, + '_openPlaygroundResult', + mockOpenPlaygroundResult + ); + + await vscode.workspace + .getConfiguration('mdb') + .update('confirmRunAll', false); + + await mdbTestExtension.testExtensionController._languageServerController.startLanguageServer(); + await mdbTestExtension.testExtensionController._playgroundController._connectToServiceProvider(); + + const mockIsPlayground = sinon.fake.returns(true); + sinon.replace(testCodeActionProvider, 'isPlayground', mockIsPlayground); + }); + + afterEach(async () => { + await vscode.commands.executeCommand( + 'workbench.action.closeActiveEditor' + ); + await vscode.workspace + .getConfiguration('mdb') + .update('confirmRunAll', true); + await mdbTestExtension.testExtensionController._connectionController.disconnect(); + mdbTestExtension.testExtensionController._connectionController.clearAllConnections(); + sinon.restore(); + }); + + test('returns undefined when text is not selected', () => { + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.be.undefined; + }); + + test('returns a run selected playground blocks action', async () => { + mdbTestExtension.testExtensionController._playgroundController._selectedText = + '123'; + + const selection = { + start: { line: 0, character: 0 }, + end: { line: 0, character: 4 }, + } as vscode.Selection; + + testCodeActionProvider.refresh({ + selection, + mode: ExportToLanguageMode.OTHER, + }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(1); + const actionCommand = codeActions[0].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal( + 'mdb.runSelectedPlaygroundBlocks' + ); + expect(actionCommand.title).to.be.equal( + 'Run selected playground blocks' + ); + + await vscode.commands.executeCommand(actionCommand.command); + + const expectedResult = { + namespace: null, + type: 'number', + content: 123, + language: 'plaintext', + }; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + expect( + mdbTestExtension.testExtensionController._playgroundController + ._isPartialRun + ).to.be.equal(true); + } + } + }); + + test('returns an export to java action with whitespaces around objects', () => { + const textFromEditor = ' { name: "Alena Khineika" } '; + const selection = { + start: { line: 0, character: 2 }, + end: { line: 0, character: 27 }, + } as vscode.Selection; + const mode = ExportToLanguageMode.QUERY; + const activeTextEditor = { + document: { getText: () => textFromEditor }, + } as vscode.TextEditor; + + mdbTestExtension.testExtensionController._playgroundController._selectedText = + textFromEditor; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.selection = + selection; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = + mode; + mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = + activeTextEditor; + + testCodeActionProvider.refresh({ selection, mode }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(6); + const actionCommand = codeActions[2].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal('mdb.exportToJava'); + expect(actionCommand.title).to.be.equal('Export To Java'); + } + } + }); + + test('exports to java and includes builders', async () => { + const textFromEditor = "{ name: '22' }"; + const selection = { + start: { line: 0, character: 0 }, + end: { line: 0, character: 14 }, + } as vscode.Selection; + const mode = ExportToLanguageMode.QUERY; + const activeTextEditor = { + document: { getText: () => textFromEditor }, + } as vscode.TextEditor; + + mdbTestExtension.testExtensionController._playgroundController._selectedText = + textFromEditor; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.selection = + selection; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = + mode; + mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = + activeTextEditor; + + testCodeActionProvider.refresh({ selection, mode }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(6); + const actionCommand = codeActions[2].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal('mdb.exportToJava'); + expect(actionCommand.title).to.be.equal('Export To Java'); + + await vscode.commands.executeCommand(actionCommand.command); + + const expectedResult = { + namespace: 'DATABASE_NAME.COLLECTION_NAME', + type: null, + content: 'new Document("name", "22")', + language: 'java', + }; + + const codeLenses = + mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); + expect(codeLenses.length).to.be.equal(3); + + // Only java queries supports builders. + await vscode.commands.executeCommand( + 'mdb.changeExportToLanguageAddons', + { + ...mdbTestExtension.testExtensionController._playgroundController + ._exportToLanguageCodeLensProvider._exportToLanguageAddons, + builders: true, + } + ); + + expectedResult.content = 'eq("name", "22")'; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + } + } + }); + + test('exports to csharp and includes import statements', async () => { + const textFromEditor = "{ name: '22' }"; + const selection = { + start: { line: 0, character: 0 }, + end: { line: 0, character: 14 }, + } as vscode.Selection; + const mode = ExportToLanguageMode.QUERY; + const activeTextEditor = { + document: { getText: () => textFromEditor }, + } as vscode.TextEditor; + + mdbTestExtension.testExtensionController._playgroundController._selectedText = + textFromEditor; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.selection = + selection; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = + mode; + mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = + activeTextEditor; + + testCodeActionProvider.refresh({ selection, mode }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(6); + const actionCommand = codeActions[3].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal('mdb.exportToCsharp'); + expect(actionCommand.title).to.be.equal('Export To C#'); + + await vscode.commands.executeCommand(actionCommand.command); + + const expectedResult = { + namespace: 'DATABASE_NAME.COLLECTION_NAME', + type: null, + content: 'new BsonDocument("name", "22")', + language: 'csharp', + }; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + + const codeLenses = + mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); + expect(codeLenses.length).to.be.equal(1); // Csharp does not support driver syntax. + + await vscode.commands.executeCommand( + 'mdb.changeExportToLanguageAddons', + { + ...mdbTestExtension.testExtensionController._playgroundController + ._exportToLanguageCodeLensProvider._exportToLanguageAddons, + importStatements: true, + } + ); + + expectedResult.content = + 'using MongoDB.Bson;\nusing MongoDB.Driver;\n\nnew BsonDocument("name", "22")'; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + } + } + }); + + test('exports to python and includes driver syntax', async () => { + const textFromEditor = "use('db'); db.coll.find({ name: '22' })"; + const selection = { + start: { line: 0, character: 24 }, + end: { line: 0, character: 38 }, + } as vscode.Selection; + const mode = ExportToLanguageMode.QUERY; + const activeTextEditor = { + document: { getText: () => textFromEditor }, + } as vscode.TextEditor; + + mdbTestExtension.testExtensionController._playgroundController._selectedText = + "{ name: '22' }"; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.selection = + selection; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = + mode; + mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = + activeTextEditor; + + testCodeActionProvider.refresh({ selection, mode }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(6); + const actionCommand = codeActions[1].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal('mdb.exportToPython'); + expect(actionCommand.title).to.be.equal('Export To Python 3'); + + await vscode.commands.executeCommand(actionCommand.command); + + let expectedResult: PlaygroundResult = { + namespace: 'DATABASE_NAME.COLLECTION_NAME', + type: null, + content: "{\n 'name': '22'\n}", + language: 'python', + }; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + + const codeLenses = + mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); + expect(codeLenses.length).to.be.equal(2); + + await vscode.commands.executeCommand( + 'mdb.changeExportToLanguageAddons', + { + ...mdbTestExtension.testExtensionController._playgroundController + ._exportToLanguageCodeLensProvider._exportToLanguageAddons, + driverSyntax: true, + } + ); + + expectedResult = { + namespace: 'db.coll', + type: null, + content: + "# Requires the PyMongo package.\n# https://api.mongodb.com/python/current\n\nclient = MongoClient('mongodb://localhost:27018/?appname=mongodb-vscode+0.0.0-dev.0')\nfilter={\n 'name': '22'\n}\n\nresult = client['db']['coll'].find(\n filter=filter\n)", + language: 'python', + }; + + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + } + } + }); + + test('exports to ruby and includes driver syntax', async () => { + const textFromEditor = "use('db'); db.coll.find({ name: '22' })"; + const selection = { + start: { line: 0, character: 24 }, + end: { line: 0, character: 38 }, + } as vscode.Selection; + const mode = ExportToLanguageMode.QUERY; + const activeTextEditor = { + document: { getText: () => textFromEditor }, + } as vscode.TextEditor; + + mdbTestExtension.testExtensionController._playgroundController._selectedText = + "{ name: '22' }"; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.selection = + selection; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = + mode; + mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = + activeTextEditor; + + testCodeActionProvider.refresh({ selection, mode }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(6); + const actionCommand = codeActions[5].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal('mdb.exportToRuby'); + expect(actionCommand.title).to.be.equal('Export To Ruby'); + + await vscode.commands.executeCommand(actionCommand.command); + + let expectedResult: PlaygroundResult = { + namespace: 'DATABASE_NAME.COLLECTION_NAME', + type: null, + content: "{\n 'name' => '22'\n}", + language: 'ruby', + }; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + + const codeLenses = + mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); + expect(codeLenses.length).to.be.equal(2); + + await vscode.commands.executeCommand( + 'mdb.changeExportToLanguageAddons', + { + ...mdbTestExtension.testExtensionController._playgroundController + ._exportToLanguageCodeLensProvider._exportToLanguageAddons, + driverSyntax: true, + } + ); + + expectedResult = { + namespace: 'db.coll', + type: null, + content: + "# Requires the MongoDB Ruby Driver\n# https://docs.mongodb.com/ruby-driver/master/\n\nclient = Mongo::Client.new('mongodb://localhost:27018/?appname=mongodb-vscode+0.0.0-dev.0', :database => 'db')\n\nresult = client.database['coll'].find({\n 'name' => '22'\n})", + language: 'ruby', + }; + + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + } + } + }); + }); + + suite('the regular JS file', () => { + const testCodeActionProvider = new PlaygroundSelectedCodeActionProvider(); + + beforeEach(() => { + const mockIsPlayground = sinon.fake.returns(false); + sinon.replace(testCodeActionProvider, 'isPlayground', mockIsPlayground); + }); + + afterEach(() => { + sinon.restore(); + }); + + test('returns undefined when text is not selected', () => { + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.be.undefined; + }); + + test('returns undefined when text is selected', () => { + mdbTestExtension.testExtensionController._playgroundController._selectedText = + '123'; + + const selection = { + start: { line: 0, character: 0 }, + end: { line: 0, character: 4 }, + } as vscode.Selection; + + testCodeActionProvider.refresh({ + selection, + mode: ExportToLanguageMode.OTHER, + }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.be.undefined; + }); + }); +}); diff --git a/src/test/suite/explorer/playgroundsExplorer.test.ts b/src/test/suite/explorer/playgroundsExplorer.test.ts index cbcba9aef..55ec58b97 100644 --- a/src/test/suite/explorer/playgroundsExplorer.test.ts +++ b/src/test/suite/explorer/playgroundsExplorer.test.ts @@ -1,6 +1,7 @@ import assert from 'assert'; import * as vscode from 'vscode'; import { before, afterEach } from 'mocha'; +import * as path from 'path'; import { mdbTestExtension } from '../stubbableMdbExtension'; import PlaygroundsTree from './../../../explorer/playgroundsTree'; @@ -44,34 +45,19 @@ suite('Playgrounds Controller Test Suite', function () { }); test('should search for playground in the workspace', async () => { - const workspaceFolders = (vscode.workspace.workspaceFolders || []).filter( - (folder) => folder.uri.scheme === 'file' - ); - const rootPath = workspaceFolders[0]?.uri.path.replace('/out/test', ''); - const rootUri = vscode.Uri.parse(rootPath); const treeController = testPlaygroundsExplorer.getTreeController(); try { - const children = await treeController.getPlaygrounds(rootUri); - + const rootPath = path.resolve(__dirname, '../../../..'); + const children = await treeController.getPlaygrounds(rootPath); assert.strictEqual(Object.keys(children).length, 7); - - const playgrounds = Object.values(children).filter( - (item: any) => item.label && item.label.split('.').pop() === 'mongodb' - ); - - assert.strictEqual(Object.keys(playgrounds).length, 7); } catch (error) { assert(false, error as Error); } }); test('should exclude folders and files specified in extension settings', async () => { - const workspaceFolders = (vscode.workspace.workspaceFolders || []).filter( - (folder) => folder.uri.scheme === 'file' - ); - const rootPath = workspaceFolders[0]?.uri.path.replace('/out/test', ''); - const rootUri = vscode.Uri.parse(rootPath); + const treeController = new PlaygroundsTree(); try { await vscode.workspace @@ -80,9 +66,8 @@ suite('Playgrounds Controller Test Suite', function () { 'excludeFromPlaygroundsSearch', excludeFromPlaygroundsSearchDefault.concat(['**/playgrounds/**']) ); - - const treeController = new PlaygroundsTree(); - const children = await treeController.getPlaygrounds(rootUri); + const rootPath = path.resolve(__dirname, '../../../..'); + const children = await treeController.getPlaygrounds(rootPath); assert.strictEqual(Object.keys(children).length, 3); } catch (error) { diff --git a/src/test/suite/language/languageServerController.test.ts b/src/test/suite/language/languageServerController.test.ts index 5a9e2cdef..ec2ce3cd0 100644 --- a/src/test/suite/language/languageServerController.test.ts +++ b/src/test/suite/language/languageServerController.test.ts @@ -6,7 +6,7 @@ import sinon from 'sinon'; import type { DataService } from 'mongodb-data-service'; import ActiveDBCodeLensProvider from '../../../editors/activeConnectionCodeLensProvider'; -import CodeActionProvider from '../../../editors/codeActionProvider'; +import PlaygroundSelectedCodeActionProvider from '../../../editors/playgroundSelectedCodeActionProvider'; import ConnectionController from '../../../connectionController'; import EditDocumentCodeLensProvider from '../../../editors/editDocumentCodeLensProvider'; import { ExplorerController } from '../../../explorer'; @@ -28,6 +28,7 @@ chai.use(require('chai-as-promised')); suite('Language Server Controller Test Suite', () => { const mockExtensionContext = new TestExtensionContext(); + // The test extension runner. mockExtensionContext.extensionPath = '../../'; const mockStorageController = new StorageController(mockExtensionContext); @@ -59,7 +60,7 @@ suite('Language Server Controller Test Suite', () => { ); const testExportToLanguageCodeLensProvider = new ExportToLanguageCodeLensProvider(); - const testCodeActionProvider = new CodeActionProvider(); + const testCodeActionProvider = new PlaygroundSelectedCodeActionProvider(); const testPlaygroundController = new PlaygroundController( testConnectionController, testLanguageServerController, diff --git a/src/test/suite/mdbExtensionController.test.ts b/src/test/suite/mdbExtensionController.test.ts index 76bf15622..9c8e20533 100644 --- a/src/test/suite/mdbExtensionController.test.ts +++ b/src/test/suite/mdbExtensionController.test.ts @@ -29,1846 +29,1675 @@ const testDatabaseURI = 'mongodb://localhost:27018'; suite('MDBExtensionController Test Suite', function () { this.timeout(10000); - const sandbox = sinon.createSandbox(); - let fakeShowInformationMessage: sinon.SinonStub; - - beforeEach(() => { - // Here we stub the showInformationMessage process because it is too much - // for the render process and leads to crashes while testing. - fakeShowInformationMessage = sinon.stub( - vscode.window, - 'showInformationMessage' - ); - }); + suite('when not connected', () => { + const sandbox = sinon.createSandbox(); + let fakeVscodeErrorMessage: SinonSpy; - afterEach(() => { - sandbox.restore(); - sinon.restore(); - }); + beforeEach(() => { + sinon.stub(vscode.window, 'showInformationMessage'); + sinon.stub(vscode.workspace, 'openTextDocument'); + sinon.stub(vscode.window, 'showTextDocument'); + fakeVscodeErrorMessage = sinon.fake(); + sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); + }); - test('mdb.viewCollectionDocuments command should call onViewCollectionDocuments on the editor controller with the collection namespace', async () => { - const mockOpenTextDocument = sinon.fake.resolves('magna carta'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - const textCollectionTree = new CollectionTreeItem( - { - name: 'testColName', - type: CollectionTypes.collection, - }, - 'testDbName', - {}, - false, - false, - null - ); + afterEach(() => { + sandbox.restore(); + sinon.restore(); + }); - await vscode.commands.executeCommand( - 'mdb.viewCollectionDocuments', - textCollectionTree - ); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].path.indexOf( - 'Results: testDbName.testColName' - ), - 0 - ); - assert(mockOpenTextDocument.firstCall.args[0].path.includes('.json')); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].scheme, - VIEW_COLLECTION_SCHEME - ); - assert( - mockOpenTextDocument.firstCall.args[0].query.includes( - 'namespace=testDbName.testColName' - ) - ); + test('mdb.addDatabase command fails when not connected to the connection', async () => { + const mockTreeItem = new ConnectionTreeItem( + 'tasty_sandwhich', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + const addDatabaseSucceeded = await vscode.commands.executeCommand( + 'mdb.addDatabase', + mockTreeItem + ); + assert( + addDatabaseSucceeded === false, + 'Expected the command handler to return a false succeeded response' + ); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'magna carta'); + const expectedMessage = + 'Please connect to this connection before adding a database.'; + assert( + fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, + `Expected an error message "${expectedMessage}" to be shown when attempting to add a database to a not connected connection found "${fakeVscodeErrorMessage.firstCall.args[0]}"` + ); + }); }); - test('mdb.viewCollectionDocuments command should also work with the documents list', async () => { - const mockOpenTextDocument = sinon.fake.resolves('magna carta'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - const textCollectionTree = new CollectionTreeItem( - { - name: 'testColName', - type: CollectionTypes.collection, - }, - 'testDbName', - {}, - false, - false, - null - ); + suite('when connected', () => { + const sandbox = sinon.createSandbox(); + let fakeShowInformationMessage: sinon.SinonStub; + let mockOpenTextDocument: SinonSpy; + let mockActiveConnectionId: SinonSpy; + let fakeVscodeErrorMessage: SinonSpy; + let fakeCreatePlaygroundFileWithContent: SinonSpy; + let fakeShowTextDocument: SinonSpy; - await vscode.commands.executeCommand( - 'mdb.viewCollectionDocuments', - textCollectionTree - ); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].path.indexOf( - 'Results: testDbName.testColName' - ), - 0 - ); - assert(mockOpenTextDocument.firstCall.args[0].path.includes('.json')); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].scheme, - VIEW_COLLECTION_SCHEME - ); - assert( - mockOpenTextDocument.firstCall.args[0].query.includes( - 'namespace=testDbName.testColName' - ) - ); + beforeEach(() => { + fakeShowInformationMessage = sinon.stub( + vscode.window, + 'showInformationMessage' + ); + mockOpenTextDocument = sinon.stub(vscode.workspace, 'openTextDocument'); + mockActiveConnectionId = sinon.fake.returns('tasty_sandwhich'); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'getActiveConnectionId', + mockActiveConnectionId + ); + fakeCreatePlaygroundFileWithContent = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._playgroundController, + '_createPlaygroundFileWithContent', + fakeCreatePlaygroundFileWithContent + ); + fakeVscodeErrorMessage = sinon.fake(); + sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); + fakeShowTextDocument = sinon.fake(); + sinon.replace(vscode.window, 'showTextDocument', fakeShowTextDocument); + }); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'magna carta'); - }); + afterEach(() => { + sandbox.restore(); + sinon.restore(); + }); - test('mdb.addConnection command should call openWebview on the webview controller', async () => { - const mockOpenWebview = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._webviewController, - 'openWebview', - mockOpenWebview - ); + test('mdb.viewCollectionDocuments command should call onViewCollectionDocuments on the editor controller with the collection namespace', async () => { + const textCollectionTree = new CollectionTreeItem( + { + name: 'testColName', + type: CollectionTypes.collection, + }, + 'testDbName', + {}, + false, + false, + null + ); + await vscode.commands.executeCommand( + 'mdb.viewCollectionDocuments', + textCollectionTree + ); + assert.strictEqual( + mockOpenTextDocument.firstCall.args[0].path.indexOf( + 'Results: testDbName.testColName' + ), + 0 + ); + assert(mockOpenTextDocument.firstCall.args[0].path.includes('.json')); + assert.strictEqual( + mockOpenTextDocument.firstCall.args[0].scheme, + VIEW_COLLECTION_SCHEME + ); + assert( + mockOpenTextDocument.firstCall.args[0].query.includes( + 'namespace=testDbName.testColName' + ) + ); + }); - await vscode.commands.executeCommand('mdb.addConnection'); - assert.strictEqual(mockOpenWebview.calledOnce, true); - }); + test('mdb.viewCollectionDocuments command should also work with the documents list', async () => { + const textCollectionTree = new CollectionTreeItem( + { + name: 'testColName', + type: CollectionTypes.collection, + }, + 'testDbName', + {}, + false, + false, + null + ); + await vscode.commands.executeCommand( + 'mdb.viewCollectionDocuments', + textCollectionTree + ); + assert.strictEqual( + mockOpenTextDocument.firstCall.args[0].path.indexOf( + 'Results: testDbName.testColName' + ), + 0 + ); + assert(mockOpenTextDocument.firstCall.args[0].path.includes('.json')); + assert.strictEqual( + mockOpenTextDocument.firstCall.args[0].scheme, + VIEW_COLLECTION_SCHEME + ); + assert( + mockOpenTextDocument.firstCall.args[0].query.includes( + 'namespace=testDbName.testColName' + ) + ); + }); - test('mdb.addConnectionWithURI command should call connectWithURI on the connection controller', async () => { - const mockConnectWithUri = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'connectWithURI', - mockConnectWithUri - ); + test('mdb.addConnection command should call openWebview on the webview controller', async () => { + const mockOpenWebview = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._webviewController, + 'openWebview', + mockOpenWebview + ); + await vscode.commands.executeCommand('mdb.addConnection'); + assert.strictEqual(mockOpenWebview.calledOnce, true); + }); - await vscode.commands.executeCommand('mdb.addConnectionWithURI'); - assert.strictEqual(mockConnectWithUri.calledOnce, true); - }); + test('mdb.addConnectionWithURI command should call connectWithURI on the connection controller', async () => { + const mockConnectWithUri = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'connectWithURI', + mockConnectWithUri + ); + await vscode.commands.executeCommand('mdb.addConnectionWithURI'); + assert.strictEqual(mockConnectWithUri.calledOnce, true); + }); - test('mdb.refreshConnection command should reset the cache on a connection tree item', async () => { - const mockTreeItem = new ConnectionTreeItem( - 'test', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); + test('mdb.refreshConnection command should reset the cache on a connection tree item', async () => { + const mockTreeItem = new ConnectionTreeItem( + 'test', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + mockTreeItem.cacheIsUpToDate = true; - mockTreeItem.cacheIsUpToDate = true; + const mockExplorerControllerRefresh = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._explorerController, + 'refresh', + mockExplorerControllerRefresh + ); + await vscode.commands.executeCommand( + 'mdb.refreshConnection', + mockTreeItem + ); + assert.strictEqual( + mockTreeItem.cacheIsUpToDate, + false, + 'Expected cache on tree item to be set to not up to date.' + ); + assert.strictEqual( + mockExplorerControllerRefresh.called, + true, + 'Expected explorer controller refresh to be called.' + ); + }); - const mockExplorerControllerRefresh = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._explorerController, - 'refresh', - mockExplorerControllerRefresh - ); + test('mdb.treeItemRemoveConnection command should call removeMongoDBConnection on the connection controller with the tree item connection id', async () => { + const mockTreeItem = new ConnectionTreeItem( + 'craving_for_pancakes_with_maple_syrup', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + const mockRemoveMongoDBConnection = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'removeMongoDBConnection', + mockRemoveMongoDBConnection + ); + await vscode.commands.executeCommand( + 'mdb.treeItemRemoveConnection', + mockTreeItem + ); + assert.strictEqual(mockRemoveMongoDBConnection.calledOnce, true); + assert.strictEqual( + mockRemoveMongoDBConnection.firstCall.args[0], + 'craving_for_pancakes_with_maple_syrup' + ); + }); - await vscode.commands.executeCommand('mdb.refreshConnection', mockTreeItem); - assert.strictEqual( - mockTreeItem.cacheIsUpToDate, - false, - 'Expected cache on tree item to be set to not up to date.' - ); - assert.strictEqual( - mockExplorerControllerRefresh.called, - true, - 'Expected explorer controller refresh to be called.' - ); - }); + test('mdb.copyConnectionString command should try to copy the driver url to the vscode env clipboard', async () => { + const mockTreeItem = new ConnectionTreeItem( + 'craving_for_pancakes_with_maple_syrup', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + const mockCopyToClipboard = sinon.fake(); + sinon.replaceGetter(vscode.env, 'clipboard', () => ({ + writeText: mockCopyToClipboard, + readText: sinon.fake(), + })); + const mockStubUri = sinon.fake.returns('weStubThisUri'); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'copyConnectionStringByConnectionId', + mockStubUri + ); + await vscode.commands.executeCommand( + 'mdb.copyConnectionString', + mockTreeItem + ); + assert.strictEqual(mockCopyToClipboard.calledOnce, true); + assert.strictEqual( + mockCopyToClipboard.firstCall.args[0], + 'weStubThisUri' + ); + }); - test('mdb.treeItemRemoveConnection command should call removeMongoDBConnection on the connection controller with the tree item connection id', async () => { - const mockTreeItem = new ConnectionTreeItem( - 'craving_for_pancakes_with_maple_syrup', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); + test('mdb.copyDatabaseName command should try to copy the database name to the vscode env clipboard', async () => { + const mockTreeItem = new DatabaseTreeItem( + 'isClubMateTheBestDrinkEver', + {}, + false, + false, + {} + ); + const mockCopyToClipboard = sinon.fake(); + sinon.replaceGetter(vscode.env, 'clipboard', () => ({ + writeText: mockCopyToClipboard, + readText: sinon.fake(), + })); + await vscode.commands.executeCommand( + 'mdb.copyDatabaseName', + mockTreeItem + ); + assert.strictEqual(mockCopyToClipboard.calledOnce, true); + assert.strictEqual( + mockCopyToClipboard.firstCall.args[0], + 'isClubMateTheBestDrinkEver' + ); + }); - const mockRemoveMongoDBConnection = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'removeMongoDBConnection', - mockRemoveMongoDBConnection - ); + test('mdb.copyCollectionName command should try to copy the collection name to the vscode env clipboard', async () => { + const mockTreeItem = new CollectionTreeItem( + { + name: 'waterBuffalo', + type: CollectionTypes.collection, + }, + 'airZebra', + {}, + false, + false, + null + ); + const mockCopyToClipboard = sinon.fake(); + sinon.replaceGetter(vscode.env, 'clipboard', () => ({ + writeText: mockCopyToClipboard, + readText: sinon.fake(), + })); + await vscode.commands.executeCommand( + 'mdb.copyCollectionName', + mockTreeItem + ); + assert( + mockCopyToClipboard.called, + 'Expected "writeText" to be called on "vscode.env.clipboard".' + ); + assert( + mockCopyToClipboard.firstCall.args[0] === 'waterBuffalo', + `Expected the clipboard to be sent the uri string "waterBuffalo", found ${mockCopyToClipboard.firstCall.args[0]}.` + ); + }); - await vscode.commands.executeCommand( - 'mdb.treeItemRemoveConnection', - mockTreeItem - ); - assert.strictEqual(mockRemoveMongoDBConnection.calledOnce, true); - assert.strictEqual( - mockRemoveMongoDBConnection.firstCall.args[0], - 'craving_for_pancakes_with_maple_syrup' - ); - }); + test('mdb.copySchemaFieldName command should try to copy the field name to the vscode env clipboard', async () => { + const mockTreeItem = new FieldTreeItem( + { + name: 'dolphins are sentient', + probability: 1, + type: 'String', + types: [], + }, + false, + {} + ); + const mockCopyToClipboard = sinon.fake(); + sinon.replaceGetter(vscode.env, 'clipboard', () => ({ + writeText: mockCopyToClipboard, + readText: sinon.fake(), + })); + const commandResult = await vscode.commands.executeCommand( + 'mdb.copySchemaFieldName', + mockTreeItem + ); + assert(commandResult); + assert( + mockCopyToClipboard.called, + 'Expected "writeText" to be called on "vscode.env.clipboard".' + ); + assert( + mockCopyToClipboard.firstCall.args[0] === 'dolphins are sentient', + `Expected the clipboard to be sent the schema field name "dolphins are sentient", found ${mockCopyToClipboard.firstCall.args[0]}.` + ); + }); - test('mdb.copyConnectionString command should try to copy the driver url to the vscode env clipboard', async () => { - const mockTreeItem = new ConnectionTreeItem( - 'craving_for_pancakes_with_maple_syrup', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); + test('mdb.refreshDatabase command should reset the cache on the database tree item', async () => { + const mockTreeItem = new DatabaseTreeItem( + 'pinkLemonade', + {}, + false, + false, + {} + ); + mockTreeItem.cacheIsUpToDate = true; - const mockCopyToClipboard = sinon.fake(); - sinon.replaceGetter(vscode.env, 'clipboard', () => ({ - writeText: mockCopyToClipboard, - readText: sinon.fake(), - })); - - const mockStubUri = sinon.fake.returns('weStubThisUri'); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'copyConnectionStringByConnectionId', - mockStubUri - ); + const mockExplorerControllerRefresh = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._explorerController, + 'refresh', + mockExplorerControllerRefresh + ); + await vscode.commands.executeCommand('mdb.refreshDatabase', mockTreeItem); + assert.strictEqual( + mockTreeItem.cacheIsUpToDate, + false, + 'Expected cache on tree item to be set to not up to date.' + ); + assert( + mockExplorerControllerRefresh.called === true, + 'Expected explorer controller refresh to be called.' + ); + }); - await vscode.commands.executeCommand( - 'mdb.copyConnectionString', - mockTreeItem - ); - assert.strictEqual(mockCopyToClipboard.calledOnce, true); - assert.strictEqual(mockCopyToClipboard.firstCall.args[0], 'weStubThisUri'); - }); + test('mdb.refreshCollection command should reset the expanded state of its children and call to refresh the explorer controller', async () => { + const mockTreeItem = new CollectionTreeItem( + { + name: 'iSawACatThatLookedLikeALionToday', + type: CollectionTypes.collection, + }, + 'airZebra', + {}, + false, + false, + null + ); + mockTreeItem.isExpanded = true; - test('mdb.copyDatabaseName command should try to copy the database name to the vscode env clipboard', async () => { - const mockTreeItem = new DatabaseTreeItem( - 'isClubMateTheBestDrinkEver', - {}, - false, - false, - {} - ); + // Set expanded. + mockTreeItem.getSchemaChild().isExpanded = true; + mockTreeItem.getDocumentListChild().isExpanded = true; - const mockCopyToClipboard = sinon.fake(); - sinon.replaceGetter(vscode.env, 'clipboard', () => ({ - writeText: mockCopyToClipboard, - readText: sinon.fake(), - })); - - await vscode.commands.executeCommand('mdb.copyDatabaseName', mockTreeItem); - assert.strictEqual(mockCopyToClipboard.calledOnce, true); - assert.strictEqual( - mockCopyToClipboard.firstCall.args[0], - 'isClubMateTheBestDrinkEver' - ); - }); + const mockExplorerControllerRefresh = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._explorerController, + 'refresh', + mockExplorerControllerRefresh + ); + await vscode.commands.executeCommand( + 'mdb.refreshCollection', + mockTreeItem + ); + assert( + mockTreeItem.getSchemaChild().isExpanded === false, + 'Expected collection tree item child to be reset to not expanded.' + ); + assert( + mockExplorerControllerRefresh.called === true, + 'Expected explorer controller refresh to be called.' + ); + }); - test('mdb.copyCollectionName command should try to copy the collection name to the vscode env clipboard', async () => { - const mockTreeItem = new CollectionTreeItem( - { - name: 'waterBuffalo', - type: CollectionTypes.collection, - }, - 'airZebra', - {}, - false, - false, - null - ); + test('mdb.refreshDocumentList command should update the document count and call to refresh the explorer controller', async () => { + let count = 9000; + const mockTreeItem = new CollectionTreeItem( + { + name: 'iSawACatThatLookedLikeALionToday', + type: CollectionTypes.collection, + }, + 'airZebra', + { estimatedCount: () => Promise.resolve(count) }, + false, + false, + null + ); + await mockTreeItem.onDidExpand(); - const mockCopyToClipboard = sinon.fake(); - sinon.replaceGetter(vscode.env, 'clipboard', () => ({ - writeText: mockCopyToClipboard, - readText: sinon.fake(), - })); + const collectionChildren = await mockTreeItem.getChildren(); + const docListTreeItem = collectionChildren[0]; + assert.strictEqual(docListTreeItem.description, '9K'); + count = 10000; + docListTreeItem.isExpanded = true; - await vscode.commands.executeCommand( - 'mdb.copyCollectionName', - mockTreeItem - ); - assert( - mockCopyToClipboard.called, - 'Expected "writeText" to be called on "vscode.env.clipboard".' - ); - assert( - mockCopyToClipboard.firstCall.args[0] === 'waterBuffalo', - `Expected the clipboard to be sent the uri string "waterBuffalo", found ${mockCopyToClipboard.firstCall.args[0]}.` - ); - }); + const mockExplorerControllerRefresh = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._explorerController, + 'refresh', + mockExplorerControllerRefresh + ); - test('mdb.copySchemaFieldName command should try to copy the field name to the vscode env clipboard', async () => { - const mockTreeItem = new FieldTreeItem( - { - name: 'dolphins are sentient', - probability: 1, - type: 'String', - types: [], - }, - false, - {} - ); + await vscode.commands.executeCommand( + 'mdb.refreshDocumentList', + docListTreeItem + ); + assert( + docListTreeItem.cacheIsUpToDate === false, + 'Expected document list cache to be out of date.' + ); + assert( + mockTreeItem.documentCount === 10000, + `Expected document count to be 10000, found ${mockTreeItem.documentCount}.` + ); + assert( + mockExplorerControllerRefresh.called === true, + 'Expected explorer controller refresh to be called.' + ); + }); - const mockCopyToClipboard = sinon.fake(); - sinon.replaceGetter(vscode.env, 'clipboard', () => ({ - writeText: mockCopyToClipboard, - readText: sinon.fake(), - })); + test('mdb.refreshSchema command should reset its cache and call to refresh the explorer controller', async () => { + const mockTreeItem = new SchemaTreeItem( + 'zebraWearwolf', + 'giraffeVampire', + {} as DataService, + false, + false, + false, + false, + {} + ); - const commandResult = await vscode.commands.executeCommand( - 'mdb.copySchemaFieldName', - mockTreeItem - ); + // Set cached. + mockTreeItem.cacheIsUpToDate = true; - assert(commandResult); - assert( - mockCopyToClipboard.called, - 'Expected "writeText" to be called on "vscode.env.clipboard".' - ); - assert( - mockCopyToClipboard.firstCall.args[0] === 'dolphins are sentient', - `Expected the clipboard to be sent the schema field name "dolphins are sentient", found ${mockCopyToClipboard.firstCall.args[0]}.` - ); - }); + const mockExplorerControllerRefresh = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._explorerController, + 'refresh', + mockExplorerControllerRefresh + ); + await vscode.commands.executeCommand('mdb.refreshSchema', mockTreeItem); + assert( + !mockTreeItem.cacheIsUpToDate, + 'Expected schema field cache to be not up to date.' + ); + assert( + mockExplorerControllerRefresh.called === true, + 'Expected explorer controller refresh to be called.' + ); + }); - test('mdb.refreshDatabase command should reset the cache on the database tree item', async () => { - const mockTreeItem = new DatabaseTreeItem( - 'pinkLemonade', - {}, - false, - false, - {} - ); + test('mdb.refreshIndexes command should reset its cache and call to refresh the explorer controller', async () => { + const mockTreeItem = new IndexListTreeItem( + 'zebraWearwolf', + 'giraffeVampire', + {} as DataService, + false, + false, + [] + ); - mockTreeItem.cacheIsUpToDate = true; + // Set cached. + mockTreeItem.cacheIsUpToDate = true; - const mockExplorerControllerRefresh = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._explorerController, - 'refresh', - mockExplorerControllerRefresh - ); + const mockExplorerControllerRefresh = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._explorerController, + 'refresh', + mockExplorerControllerRefresh + ); + await vscode.commands.executeCommand('mdb.refreshIndexes', mockTreeItem); + assert( + !mockTreeItem.cacheIsUpToDate, + 'Expected schema field cache to be not up to date.' + ); + assert( + mockExplorerControllerRefresh.called === true, + 'Expected explorer controller refresh to be called.' + ); + }); - await vscode.commands.executeCommand('mdb.refreshDatabase', mockTreeItem); - assert.strictEqual( - mockTreeItem.cacheIsUpToDate, - false, - 'Expected cache on tree item to be set to not up to date.' - ); - assert( - mockExplorerControllerRefresh.called === true, - 'Expected explorer controller refresh to be called.' - ); - }); + test('mdb.addDatabase should create a MongoDB playground with create collection template', async () => { + const mockTreeItem = new ConnectionTreeItem( + 'tasty_sandwhich', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + await vscode.commands.executeCommand('mdb.addDatabase', mockTreeItem); - test('mdb.refreshCollection command should reset the expanded state of its children and call to refresh the explorer controller', async () => { - const mockTreeItem = new CollectionTreeItem( - { - name: 'iSawACatThatLookedLikeALionToday', - type: CollectionTypes.collection, - }, - 'airZebra', - {}, - false, - false, - null - ); + const content = fakeCreatePlaygroundFileWithContent.firstCall.args[0]; + assert(content.includes('// Create a new database.')); + assert(content.includes('NEW_DATABASE_NAME')); + assert(content.includes('NEW_COLLECTION_NAME')); + }); - mockTreeItem.isExpanded = true; + test('mdb.addCollection should create a MongoDB playground with create collection template', async () => { + const mockTreeItem = new DatabaseTreeItem( + 'iceCreamDB', + {}, + false, + false, + {} + ); + await vscode.commands.executeCommand('mdb.addCollection', mockTreeItem); - // Set expanded. - mockTreeItem.getSchemaChild().isExpanded = true; - mockTreeItem.getDocumentListChild().isExpanded = true; + const content = fakeCreatePlaygroundFileWithContent.firstCall.args[0]; + assert(content.includes('// The current database to use.')); + assert(content.includes('iceCreamDB')); + assert(content.includes('NEW_COLLECTION_NAME')); + assert(!content.includes('time-series')); + }); - const mockExplorerControllerRefresh = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._explorerController, - 'refresh', - mockExplorerControllerRefresh - ); + test('mdb.searchForDocuments should create a MongoDB playground with search template', async () => { + await vscode.commands.executeCommand('mdb.searchForDocuments', { + databaseName: 'dbbbbbName', + collectionName: 'colllllllllName', + }); - await vscode.commands.executeCommand('mdb.refreshCollection', mockTreeItem); - assert( - mockTreeItem.getSchemaChild().isExpanded === false, - 'Expected collection tree item child to be reset to not expanded.' - ); - assert( - mockExplorerControllerRefresh.called === true, - 'Expected explorer controller refresh to be called.' - ); - }); + const content = fakeCreatePlaygroundFileWithContent.firstCall.args[0]; + assert( + content.includes('Search for documents in the current collection.') + ); + assert(content.includes('dbbbbbName')); + assert(content.includes('colllllllllName')); + }); - test('mdb.refreshDocumentList command should update the document count and call to refresh the explorer controller', async () => { - let count = 9000; - const mockTreeItem = new CollectionTreeItem( - { - name: 'iSawACatThatLookedLikeALionToday', - type: CollectionTypes.collection, - }, - 'airZebra', - { estimatedCount: () => Promise.resolve(count) }, - false, - false, - null - ); + test('mdb.createIndexFromTreeView should create a MongoDB playground with index template', async () => { + await vscode.commands.executeCommand('mdb.createIndexFromTreeView', { + databaseName: 'dbbbbbName', + collectionName: 'colllllllllName', + }); - await mockTreeItem.onDidExpand(); + const content = fakeCreatePlaygroundFileWithContent.firstCall.args[0]; + assert(content.includes('Create a new index in the collection.')); + assert(content.includes('dbbbbbName')); + assert(content.includes('colllllllllName')); + }); - const collectionChildren = await mockTreeItem.getChildren(); - const docListTreeItem = collectionChildren[0]; + test('mdb.createPlayground should create a MongoDB playground with default template', async () => { + const mockGetConfiguration = sinon.fake.returns({ + get: () => true, + }); + sinon.replace(vscode.workspace, 'getConfiguration', mockGetConfiguration); + await vscode.commands.executeCommand('mdb.createPlayground'); - assert(docListTreeItem.description === '9K'); + const content = fakeCreatePlaygroundFileWithContent.firstCall.args[0]; + assert(content.includes('// MongoDB Playground')); + }); - count = 10000; + test('mdb.createPlayground command should create a MongoDB playground without template', async () => { + const mockGetConfiguration = sinon.fake.returns({ + get: () => false, + }); + sinon.replace(vscode.workspace, 'getConfiguration', mockGetConfiguration); + await vscode.commands.executeCommand('mdb.createPlayground'); - docListTreeItem.isExpanded = true; + const content = fakeCreatePlaygroundFileWithContent.firstCall.args[0]; + assert.strictEqual(content, ''); + }); - const mockExplorerControllerRefresh = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._explorerController, - 'refresh', - mockExplorerControllerRefresh - ); + test('mdb.addDatabase command fails when disconnecting', async () => { + const mockTreeItem = new ConnectionTreeItem( + 'tasty_sandwhich', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('theDbName'); + mockInputBoxResolves.onCall(1).resolves('theCollectionName'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - await vscode.commands.executeCommand( - 'mdb.refreshDocumentList', - docListTreeItem - ); + const mockIsDisconnecting = sinon.fake.returns(true); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'isDisconnecting', + mockIsDisconnecting + ); - assert( - docListTreeItem.cacheIsUpToDate === false, - 'Expected document list cache to be out of date.' - ); - assert( - mockTreeItem.documentCount === 10000, - `Expected document count to be 10000, found ${mockTreeItem.documentCount}.` - ); - assert( - mockExplorerControllerRefresh.called === true, - 'Expected explorer controller refresh to be called.' - ); - }); + const addDatabaseSucceeded = await vscode.commands.executeCommand( + 'mdb.addDatabase', + mockTreeItem + ); + assert( + addDatabaseSucceeded === false, + 'Expected the add database command handler to return a false succeeded response' + ); - test('mdb.refreshSchema command should reset its cache and call to refresh the explorer controller', async () => { - const mockTreeItem = new SchemaTreeItem( - 'zebraWearwolf', - 'giraffeVampire', - {} as DataService, - false, - false, - false, - false, - {} - ); + const expectedMessage = + 'Unable to add database: currently disconnecting.'; + assert( + fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, + `Expected the error message "${expectedMessage}" to be shown when attempting to add a database while disconnecting, found "${fakeVscodeErrorMessage.firstCall.args[0]}"` + ); + }); - // Set cached. - mockTreeItem.cacheIsUpToDate = true; + test('mdb.addDatabase command fails when connecting', async () => { + const mockTreeItem = new ConnectionTreeItem( + 'tasty_sandwhich', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('theDbName'); + mockInputBoxResolves.onCall(1).resolves('theCollectionName'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockExplorerControllerRefresh = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._explorerController, - 'refresh', - mockExplorerControllerRefresh - ); + const mockIsConnecting = sinon.fake.returns(true); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'isConnecting', + mockIsConnecting + ); - await vscode.commands.executeCommand('mdb.refreshSchema', mockTreeItem); - assert( - !mockTreeItem.cacheIsUpToDate, - 'Expected schema field cache to be not up to date.' - ); - assert( - mockExplorerControllerRefresh.called === true, - 'Expected explorer controller refresh to be called.' - ); - }); + const addDatabaseSucceeded = await vscode.commands.executeCommand( + 'mdb.addDatabase', + mockTreeItem + ); + assert( + addDatabaseSucceeded === false, + 'Expected the add database command handler to return a false succeeded response' + ); - test('mdb.refreshIndexes command should reset its cache and call to refresh the explorer controller', async () => { - const mockTreeItem = new IndexListTreeItem( - 'zebraWearwolf', - 'giraffeVampire', - {} as DataService, - false, - false, - [] - ); + const expectedMessage = 'Unable to add database: currently connecting.'; + assert( + fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, + `Expected the error message "${expectedMessage}" to be shown when attempting to add a database while disconnecting, found "${fakeVscodeErrorMessage.firstCall.args[0]}"` + ); + }); - // Set cached. - mockTreeItem.cacheIsUpToDate = true; + test('mdb.addCollection command fails when disconnecting', async () => { + const mockTreeItem = new DatabaseTreeItem( + 'iceCreamDB', + {}, + false, + false, + {} + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('mintChocolateChips'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockExplorerControllerRefresh = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._explorerController, - 'refresh', - mockExplorerControllerRefresh - ); + const mockIsDisconnecting = sinon.fake.returns(true); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'isDisconnecting', + mockIsDisconnecting + ); - await vscode.commands.executeCommand('mdb.refreshIndexes', mockTreeItem); - assert( - !mockTreeItem.cacheIsUpToDate, - 'Expected schema field cache to be not up to date.' - ); - assert( - mockExplorerControllerRefresh.called === true, - 'Expected explorer controller refresh to be called.' - ); - }); + const addCollectionSucceeded = await vscode.commands.executeCommand( + 'mdb.addCollection', + mockTreeItem + ); + assert( + addCollectionSucceeded === false, + 'Expected the add collection command handler to return a false succeeded response' + ); + const expectedMessage = + 'Unable to add collection: currently disconnecting.'; + assert( + fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, + `Expected "${expectedMessage}" when adding a database to a not connected connection, recieved "${fakeVscodeErrorMessage.firstCall.args[0]}"` + ); + }); - test('mdb.addDatabase command fails when not connected to the connection', async () => { - const mockTreeItem = new ConnectionTreeItem( - 'tasty_sandwhich', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); + // https://code.visualstudio.com/api/references/contribution-points#Sorting-of-groups + test('mdb.dropCollection calls data service to drop the collection after inputting the collection name', async () => { + let calledNamespace = ''; + const testCollectionTreeItem = new CollectionTreeItem( + { name: 'testColName', type: CollectionTypes.collection }, + 'testDbName', + { + dropCollection: (namespace, callback): void => { + calledNamespace = namespace; + callback(null, true); + }, + }, + false, + false, + null + ); - const fakeVscodeErrorMessage = sinon.fake(); - sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('testColName'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const addDatabaseSucceeded = await vscode.commands.executeCommand( - 'mdb.addDatabase', - mockTreeItem - ); - assert( - addDatabaseSucceeded === false, - 'Expected the command handler to return a false succeeded response' - ); - const expectedMessage = - 'Please connect to this connection before adding a database.'; - assert( - fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, - `Expected an error message "${expectedMessage}" to be shown when attempting to add a database to a not connected connection found "${fakeVscodeErrorMessage.firstCall.args[0]}"` - ); - }); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropCollection', + testCollectionTreeItem + ); + assert(successfullyDropped); + assert.strictEqual(calledNamespace, 'testDbName.testColName'); + }); - test('mdb.addDatabase should create a MongoDB playground with create collection template', async () => { - const mockTreeItem = new ConnectionTreeItem( - 'tasty_sandwhich', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); + test('mdb.dropCollection fails when a collection doesnt exist', async () => { + const testConnectionController = + mdbTestExtension.testExtensionController._connectionController; + await testConnectionController.addNewConnectionStringAndConnect( + testDatabaseURI + ); - const mockActiveConnectionId = sinon.fake.returns('tasty_sandwhich'); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'getActiveConnectionId', - mockActiveConnectionId - ); + const testCollectionTreeItem = new CollectionTreeItem( + { name: 'doesntExistColName', type: CollectionTypes.collection }, + 'doesntExistDBName', + testConnectionController.getActiveDataService(), + false, + false, + null + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('doesntExistColName'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockOpenTextDocument = sinon.fake.resolves('untitled'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropCollection', + testCollectionTreeItem + ); + assert( + successfullyDropped === false, + 'Expected the drop collection command handler to return a false succeeded response' + ); - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); + const expectedMessage = 'Drop collection failed: ns not found'; + assert( + fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, + `Expected "${expectedMessage}" when dropping a collection that doesn't exist, recieved "${fakeVscodeErrorMessage.firstCall.args[0]}"` + ); + await testConnectionController.disconnect(); + testConnectionController.clearAllConnections(); + }); - await vscode.commands.executeCommand('mdb.addDatabase', mockTreeItem); + test('mdb.dropCollection fails when the input doesnt match the collection name', async () => { + const testCollectionTreeItem = new CollectionTreeItem( + { name: 'orange', type: CollectionTypes.collection }, + 'fruitsThatAreTasty', + {}, + false, + false, + null + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('apple'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - assert(mockOpenTextDocument.firstCall.args[0].language === 'mongodb'); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes( - '// Create a new database.' - ) - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes( - 'NEW_DATABASE_NAME' - ) - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes( - 'NEW_COLLECTION_NAME' - ) - ); - }); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropCollection', + testCollectionTreeItem + ); + assert( + successfullyDropped === false, + 'Expected the drop collection command handler to return a false succeeded response' + ); + }); - test('mdb.addDatabase command fails when disconnecting', async () => { - const mockTreeItem = new ConnectionTreeItem( - 'tasty_sandwhich', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); + test('mdb.dropCollection fails when the collection name input is empty', async () => { + const testCollectionTreeItem = new CollectionTreeItem( + { name: 'orange', type: CollectionTypes.view }, + 'fruitsThatAreTasty', + {}, + false, + false, + null + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves(/* Return undefined. */); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('theDbName'); - mockInputBoxResolves.onCall(1).resolves('theCollectionName'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropCollection', + testCollectionTreeItem + ); + assert( + successfullyDropped === false, + 'Expected the drop collection command handler to return a false succeeded response' + ); + }); - const mockIsDisconnecting = sinon.fake.returns(true); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'isDisconnecting', - mockIsDisconnecting - ); + test('mdb.dropDatabase calls dataservice to drop the database after inputting the database name', async () => { + let calledDatabaseName = ''; + const testDatabaseTreeItem = new DatabaseTreeItem( + 'iMissTangerineAltoids', + { + dropDatabase: (dbName, callback): void => { + calledDatabaseName = dbName; + callback(null, true); + }, + }, + false, + false, + {} + ); - const fakeVscodeErrorMessage = sinon.fake(); - sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('iMissTangerineAltoids'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockActiveConnectionId = sinon.fake.returns('tasty_sandwhich'); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'getActiveConnectionId', - mockActiveConnectionId - ); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropDatabase', + testDatabaseTreeItem + ); + assert.strictEqual(successfullyDropped, true); + assert.strictEqual(calledDatabaseName, 'iMissTangerineAltoids'); + }); - const addDatabaseSucceeded = await vscode.commands.executeCommand( - 'mdb.addDatabase', - mockTreeItem - ); - assert( - addDatabaseSucceeded === false, - 'Expected the add database command handler to return a false succeeded response' - ); - const expectedMessage = 'Unable to add database: currently disconnecting.'; - assert( - fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, - `Expected the error message "${expectedMessage}" to be shown when attempting to add a database while disconnecting, found "${fakeVscodeErrorMessage.firstCall.args[0]}"` - ); - }); + test('mdb.dropDatabase succeeds even when a database doesnt exist (mdb behavior)', async () => { + const testConnectionController = + mdbTestExtension.testExtensionController._connectionController; + await testConnectionController.addNewConnectionStringAndConnect( + testDatabaseURI + ); - test('mdb.addDatabase command fails when connecting', async () => { - const mockTreeItem = new ConnectionTreeItem( - 'tasty_sandwhich', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('theDbName'); - mockInputBoxResolves.onCall(1).resolves('theCollectionName'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const mockIsConnecting = sinon.fake.returns(true); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'isConnecting', - mockIsConnecting - ); - - const fakeVscodeErrorMessage = sinon.fake(); - sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); - const mockActiveConnectionId = sinon.fake.returns('tasty_sandwhich'); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'getActiveConnectionId', - mockActiveConnectionId - ); - - const addDatabaseSucceeded = await vscode.commands.executeCommand( - 'mdb.addDatabase', - mockTreeItem - ); - assert( - addDatabaseSucceeded === false, - 'Expected the add database command handler to return a false succeeded response' - ); - const expectedMessage = 'Unable to add database: currently connecting.'; - assert( - fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, - `Expected the error message "${expectedMessage}" to be shown when attempting to add a database while disconnecting, found "${fakeVscodeErrorMessage.firstCall.args[0]}"` - ); - }); - - test('mdb.addCollection should create a MongoDB playground with create collection template', async () => { - const mockTreeItem = new DatabaseTreeItem( - 'iceCreamDB', - {}, - false, - false, - {} - ); + const testDatabaseTreeItem = new DatabaseTreeItem( + 'narnia____a', + testConnectionController.getActiveDataService(), + false, + false, + {} + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('narnia____a'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockActiveConnectionId = sinon.fake.returns('tasty_sandwhich'); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'getActiveConnectionId', - mockActiveConnectionId - ); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropDatabase', + testDatabaseTreeItem + ); + assert( + successfullyDropped, + 'Expected the drop database command handler to return a successful boolean response' + ); + assert( + fakeVscodeErrorMessage.called === false, + 'Expected no error messages' + ); + }); - const mockOpenTextDocument = sinon.fake.resolves('untitled'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); + test('mdb.dropDatabase fails when the input doesnt match the database name', async () => { + const testDatabaseTreeItem = new DatabaseTreeItem( + 'cinnamonToastCrunch', + {}, + false, + false, + {} + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('apple'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropDatabase', + testDatabaseTreeItem + ); + assert( + successfullyDropped === false, + 'Expected the drop database command handler to return a false succeeded response' + ); + }); - await vscode.commands.executeCommand('mdb.addCollection', mockTreeItem); + test('mdb.dropDatabase fails when the database name input is empty', async () => { + const testDatabaseTreeItem = new DatabaseTreeItem( + 'blueBerryPancakesAndTheSmellOfBacon', + {}, + false, + false, + {} + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves(/* Return undefined. */); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - assert(mockOpenTextDocument.firstCall.args[0].language === 'mongodb'); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes( - '// The current database to use.' - ) - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes('iceCreamDB') - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes( - 'NEW_COLLECTION_NAME' - ) - ); - assert( - !mockOpenTextDocument.firstCall.args[0].content.includes('time-series') - ); - }); + const successfullyDropped = await vscode.commands.executeCommand( + 'mdb.dropDatabase', + testDatabaseTreeItem + ); + assert( + successfullyDropped === false, + 'Expected the drop database command handler to return a false succeeded response' + ); + }); - test('mdb.addCollection command fails when disconnecting', async () => { - const mockTreeItem = new DatabaseTreeItem( - 'iceCreamDB', - {}, - false, - false, - {} - ); + test('mdb.renameConnection fails when the name input is empty', async () => { + mdbTestExtension.testExtensionController._connectionController._connections.blueBerryPancakesAndTheSmellOfBacon = + { + id: 'blueBerryPancakesAndTheSmellOfBacon', + connectionOptions: { connectionString: 'mongodb://localhost' }, + name: 'NAAAME', + storageLocation: StorageLocation.NONE, + }; + + const mockTreeItem = new ConnectionTreeItem( + 'blueBerryPancakesAndTheSmellOfBacon', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('mintChocolateChips'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves(/* Return undefined. */); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const mockIsDisconnecting = sinon.fake.returns(true); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'isDisconnecting', - mockIsDisconnecting - ); + const successfullyRenamed = await vscode.commands.executeCommand( + 'mdb.renameConnection', + mockTreeItem + ); + assert( + successfullyRenamed === false, + 'Expected the rename connection command handler to return a false succeeded response' + ); + assert( + mdbTestExtension.testExtensionController._connectionController + ._connections.blueBerryPancakesAndTheSmellOfBacon.name === 'NAAAME', + 'Expected connection not to be ranamed.' + ); + mdbTestExtension.testExtensionController._connectionController.clearAllConnections(); + }); - const fakeVscodeErrorMessage = sinon.fake(); - sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); + test('mdb.renameConnection updates the name of a connection', async () => { + mdbTestExtension.testExtensionController._connectionController._connections.blueBerryPancakesAndTheSmellOfBacon = + { + id: 'blueBerryPancakesAndTheSmellOfBacon', + name: 'NAAAME', + connectionOptions: { connectionString: 'mongodb://localhost' }, + storageLocation: StorageLocation.NONE, + }; + + const mockTreeItem = new ConnectionTreeItem( + 'blueBerryPancakesAndTheSmellOfBacon', + vscode.TreeItemCollapsibleState.None, + false, + mdbTestExtension.testExtensionController._connectionController, + false, + {} + ); + const mockInputBoxResolves: any = sinon.stub(); + mockInputBoxResolves.onCall(0).resolves('orange juice'); + sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - const addCollectionSucceeded = await vscode.commands.executeCommand( - 'mdb.addCollection', - mockTreeItem - ); - assert( - addCollectionSucceeded === false, - 'Expected the add collection command handler to return a false succeeded response' - ); - const expectedMessage = - 'Unable to add collection: currently disconnecting.'; - assert( - fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, - `Expected "${expectedMessage}" when adding a database to a not connected connection, recieved "${fakeVscodeErrorMessage.firstCall.args[0]}"` - ); - }); + const successfullyRenamed = await vscode.commands.executeCommand( + 'mdb.renameConnection', + mockTreeItem + ); + assert.strictEqual(successfullyRenamed, true); + assert.strictEqual( + mdbTestExtension.testExtensionController._connectionController + ._connections.blueBerryPancakesAndTheSmellOfBacon.name, + 'orange juice' + ); + mdbTestExtension.testExtensionController._connectionController.clearAllConnections(); + }); - // https://code.visualstudio.com/api/references/contribution-points#Sorting-of-groups - - test('mdb.dropCollection calls data service to drop the collection after inputting the collection name', async () => { - let calledNamespace = ''; - const testCollectionTreeItem = new CollectionTreeItem( - { name: 'testColName', type: CollectionTypes.collection }, - 'testDbName', - { - dropCollection: (namespace, callback): void => { - calledNamespace = namespace; - callback(null, true); + test('mdb.openMongoDBDocumentFromTree openes a document from the sidebar and saves it to MongoDB', async () => { + const mockDocument = { + _id: 'pancakes', + name: '', + time: { + $time: '12345', }, - }, - false, - false, - null - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('testColName'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropCollection', - testCollectionTreeItem - ); - assert(successfullyDropped); - assert(calledNamespace === 'testDbName.testColName'); - }); - - test('mdb.dropCollection fails when a collection doesnt exist', async () => { - const testConnectionController = - mdbTestExtension.testExtensionController._connectionController; - - await testConnectionController.addNewConnectionStringAndConnect( - testDatabaseURI - ); - const testCollectionTreeItem = new CollectionTreeItem( - { name: 'doesntExistColName', type: CollectionTypes.collection }, - 'doesntExistDBName', - testConnectionController.getActiveDataService(), - false, - false, - null - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('doesntExistColName'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const fakeVscodeErrorMessage = sinon.fake(); - sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); - - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropCollection', - testCollectionTreeItem - ); - assert( - successfullyDropped === false, - 'Expected the drop collection command handler to return a false succeeded response' - ); - const expectedMessage = 'Drop collection failed: ns not found'; - assert( - fakeVscodeErrorMessage.firstCall.args[0] === expectedMessage, - `Expected "${expectedMessage}" when dropping a collection that doesn't exist, recieved "${fakeVscodeErrorMessage.firstCall.args[0]}"` - ); - - await testConnectionController.disconnect(); - testConnectionController.clearAllConnections(); - }); - - test('mdb.dropCollection fails when the input doesnt match the collection name', async () => { - const testCollectionTreeItem = new CollectionTreeItem( - { name: 'orange', type: CollectionTypes.collection }, - 'fruitsThatAreTasty', - {}, - false, - false, - null - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('apple'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropCollection', - testCollectionTreeItem - ); - assert( - successfullyDropped === false, - 'Expected the drop collection command handler to return a false succeeded response' - ); - }); - - test('mdb.dropCollection fails when the collection name input is empty', async () => { - const testCollectionTreeItem = new CollectionTreeItem( - { name: 'orange', type: CollectionTypes.view }, - 'fruitsThatAreTasty', - {}, - false, - false, - null - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves(/* Return undefined. */); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); + }; + const mockGet = sinon.fake.returns('pancakes'); + sinon.replace( + mdbTestExtension.testExtensionController._editorsController + ._documentIdStore, + 'get', + mockGet + ); - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropCollection', - testCollectionTreeItem - ); - assert( - successfullyDropped === false, - 'Expected the drop collection command handler to return a false succeeded response' - ); - }); + const activeTextEditor = mockTextEditor; + activeTextEditor.document.uri = vscode.Uri.parse( + [ + 'VIEW_DOCUMENT_SCHEME:/', + 'waffle.house:pancakes.json?', + 'namespace=waffle.house&', + 'connectionId=tasty_sandwhich&', + 'documentId=93333a0d-83f6-4e6f-a575-af7ea6187a4a&', + 'source=treeview', + ].join('') + ); + activeTextEditor.document.getText = () => JSON.stringify(mockDocument); + sandbox.replaceGetter( + vscode.window, + 'activeTextEditor', + () => activeTextEditor + ); - test('mdb.dropDatabase calls dataservice to drop the database after inputting the database name', async () => { - let calledDatabaseName = ''; - const testDatabaseTreeItem = new DatabaseTreeItem( - 'iMissTangerineAltoids', - { - dropDatabase: (dbName, callback): void => { - calledDatabaseName = dbName; - callback(null, true); + const mockGetActiveDataService = sinon.fake.returns({ + find: () => { + return Promise.resolve([mockDocument]); }, - }, - false, - false, - {} - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('iMissTangerineAltoids'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropDatabase', - testDatabaseTreeItem - ); - assert.strictEqual(successfullyDropped, true); - assert.strictEqual(calledDatabaseName, 'iMissTangerineAltoids'); - }); - - test('mdb.dropDatabase succeeds even when a database doesnt exist (mdb behavior)', async () => { - const testConnectionController = - mdbTestExtension.testExtensionController._connectionController; - - await testConnectionController.addNewConnectionStringAndConnect( - testDatabaseURI - ); - const testDatabaseTreeItem = new DatabaseTreeItem( - 'narnia____a', - testConnectionController.getActiveDataService(), - false, - false, - {} - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('narnia____a'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const fakeVscodeErrorMessage = sinon.fake(); - sinon.replace(vscode.window, 'showErrorMessage', fakeVscodeErrorMessage); - - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropDatabase', - testDatabaseTreeItem - ); - assert( - successfullyDropped, - 'Expected the drop database command handler to return a successful boolean response' - ); - assert( - fakeVscodeErrorMessage.called === false, - 'Expected no error messages' - ); - }); - - test('mdb.dropDatabase fails when the input doesnt match the database name', async () => { - const testDatabaseTreeItem = new DatabaseTreeItem( - 'cinnamonToastCrunch', - {}, - false, - false, - {} - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('apple'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropDatabase', - testDatabaseTreeItem - ); - assert( - successfullyDropped === false, - 'Expected the drop database command handler to return a false succeeded response' - ); - }); + findOneAndReplace: ( + namespace: string, + filter: object, + replacement: object, + options: object, + callback: (error: Error | null, result: object) => void + ) => { + mockDocument.name = 'something sweet'; + + return callback(null, mockDocument); + }, + }); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'getActiveDataService', + mockGetActiveDataService + ); - test('mdb.dropDatabase fails when the database name input is empty', async () => { - const testDatabaseTreeItem = new DatabaseTreeItem( - 'blueBerryPancakesAndTheSmellOfBacon', - {}, - false, - false, - {} - ); + const documentItem = new DocumentTreeItem( + mockDocument, + 'waffle.house', + 0, + {} as DataService, + () => Promise.resolve() + ); + await vscode.commands.executeCommand( + 'mdb.openMongoDBDocumentFromTree', + documentItem + ); + assert(mockOpenTextDocument.firstCall.args[0].path.includes('.json')); + assert.strictEqual( + mockOpenTextDocument.firstCall.args[0].scheme, + 'VIEW_DOCUMENT_SCHEME' + ); + assert( + mockOpenTextDocument.firstCall.args[0].query.includes('documentId=') + ); + assert( + mockOpenTextDocument.firstCall.args[0].query.includes('connectionId=') + ); + assert( + mockOpenTextDocument.firstCall.args[0].query.includes('source=treeview') + ); + assert( + mockOpenTextDocument.firstCall.args[0].query.includes( + 'namespace=waffle.house' + ) + ); + await vscode.commands.executeCommand('mdb.saveMongoDBDocument'); + assert.strictEqual(mockDocument.name, 'something sweet'); + assert.strictEqual(mockDocument.time.$time, '12345'); - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves(/* Return undefined. */); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); + const expectedMessage = + "The document was saved successfully to 'waffle.house'"; - const successfullyDropped = await vscode.commands.executeCommand( - 'mdb.dropDatabase', - testDatabaseTreeItem - ); - assert( - successfullyDropped === false, - 'Expected the drop database command handler to return a false succeeded response' - ); - }); + assert.strictEqual( + fakeShowInformationMessage.firstCall.args[0], + expectedMessage + ); + }); - test('mdb.renameConnection fails when the name input is empty', async () => { - mdbTestExtension.testExtensionController._connectionController._connections.blueBerryPancakesAndTheSmellOfBacon = - { - id: 'blueBerryPancakesAndTheSmellOfBacon', - connectionOptions: { connectionString: 'mongodb://localhost' }, - name: 'NAAAME', - storageLocation: StorageLocation.NONE, + test('mdb.openMongoDBDocumentFromTree openes a document from a tree with a treeview source', async () => { + const mockDocument = { + _id: 'pancakes', + name: '', + time: { + $time: '12345', + }, }; + const documentItem = new DocumentTreeItem( + mockDocument, + 'waffle.house', + 0, + {} as DataService, + () => Promise.resolve() + ); + const mockFetchDocument = sinon.fake.resolves(null); + sinon.replace( + mdbTestExtension.testExtensionController._editorsController + ._mongoDBDocumentService, + 'fetchDocument', + mockFetchDocument + ); + await vscode.commands.executeCommand( + 'mdb.openMongoDBDocumentFromTree', + documentItem + ); + assert.strictEqual( + mockFetchDocument.firstCall.args[0].source, + 'treeview' + ); + }); - const mockTreeItem = new ConnectionTreeItem( - 'blueBerryPancakesAndTheSmellOfBacon', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves(/* Return undefined. */); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const successfullyRenamed = await vscode.commands.executeCommand( - 'mdb.renameConnection', - mockTreeItem - ); - assert( - successfullyRenamed === false, - 'Expected the rename connection command handler to return a false succeeded response' - ); - assert( - mdbTestExtension.testExtensionController._connectionController - ._connections.blueBerryPancakesAndTheSmellOfBacon.name === 'NAAAME', - 'Expected connection not to be ranamed.' - ); - mdbTestExtension.testExtensionController._connectionController.clearAllConnections(); - }); - - test('mdb.renameConnection updates the name of a connection', async () => { - mdbTestExtension.testExtensionController._connectionController._connections.blueBerryPancakesAndTheSmellOfBacon = - { - id: 'blueBerryPancakesAndTheSmellOfBacon', - name: 'NAAAME', - connectionOptions: { connectionString: 'mongodb://localhost' }, - storageLocation: StorageLocation.NONE, + test('mdb.openMongoDBDocumentFromCodeLens openes a document from a playground results with a playground source', async () => { + const documentItem = { + source: 'playground', + line: 1, + documentId: '93333a0d-83f6-4e6f-a575-af7ea6187a4a', + namespace: 'db.coll', + connectionId: null, }; - - const mockTreeItem = new ConnectionTreeItem( - 'blueBerryPancakesAndTheSmellOfBacon', - vscode.TreeItemCollapsibleState.None, - false, - mdbTestExtension.testExtensionController._connectionController, - false, - {} - ); - - const mockInputBoxResolves: any = sinon.stub(); - mockInputBoxResolves.onCall(0).resolves('orange juice'); - sinon.replace(vscode.window, 'showInputBox', mockInputBoxResolves); - - const successfullyRenamed = await vscode.commands.executeCommand( - 'mdb.renameConnection', - mockTreeItem - ); - assert.strictEqual(successfullyRenamed, true); - assert.strictEqual( - mdbTestExtension.testExtensionController._connectionController - ._connections.blueBerryPancakesAndTheSmellOfBacon.name, - 'orange juice' - ); - mdbTestExtension.testExtensionController._connectionController.clearAllConnections(); - }); - - test('documents can be opened from the sidebar and saved to MongoDB', async () => { - const mockDocument = { - _id: 'pancakes', - name: '', - time: { - $time: '12345', - }, - }; - - const mockOpenTextDocument = sinon.fake.resolves('magna carta'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - const mockGet = sinon.fake.returns('pancakes'); - sinon.replace( - mdbTestExtension.testExtensionController._editorsController - ._documentIdStore, - 'get', - mockGet - ); - - const activeTextEditor = mockTextEditor; - activeTextEditor.document.uri = vscode.Uri.parse( - [ - 'VIEW_DOCUMENT_SCHEME:/', - 'waffle.house:pancakes.json?', - 'namespace=waffle.house&', - 'connectionId=tasty_sandwhich&', - 'documentId=93333a0d-83f6-4e6f-a575-af7ea6187a4a&', - 'source=treeview', - ].join('') - ); - activeTextEditor.document.getText = () => JSON.stringify(mockDocument); - sandbox.replaceGetter( - vscode.window, - 'activeTextEditor', - () => activeTextEditor - ); - - const mockActiveConnectionId = sinon.fake.returns('tasty_sandwhich'); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'getActiveConnectionId', - mockActiveConnectionId - ); - - const mockGetActiveDataService = sinon.fake.returns({ - find: () => { - return Promise.resolve([mockDocument]); - }, - findOneAndReplace: ( - namespace: string, - filter: object, - replacement: object, - options: object, - callback: (error: Error | null, result: object) => void - ) => { - mockDocument.name = 'something sweet'; - - return callback(null, mockDocument); - }, + const mockFetchDocument = sinon.fake.resolves(null); + sinon.replace( + mdbTestExtension.testExtensionController._editorsController + ._mongoDBDocumentService, + 'fetchDocument', + mockFetchDocument + ); + await vscode.commands.executeCommand( + 'mdb.openMongoDBDocumentFromCodeLens', + documentItem + ); + assert.strictEqual( + mockFetchDocument.firstCall.args[0].source, + 'playground' + ); }); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'getActiveDataService', - mockGetActiveDataService - ); - - const documentItem = new DocumentTreeItem( - mockDocument, - 'waffle.house', - 0, - {} as DataService, - () => Promise.resolve() - ); - - await vscode.commands.executeCommand( - 'mdb.openMongoDBDocumentFromTree', - documentItem - ); - - assert(mockOpenTextDocument.firstCall.args[0].path.includes('.json')); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].scheme, - 'VIEW_DOCUMENT_SCHEME' - ); - assert( - mockOpenTextDocument.firstCall.args[0].query.includes('documentId=') - ); - assert( - mockOpenTextDocument.firstCall.args[0].query.includes('connectionId=') - ); - assert( - mockOpenTextDocument.firstCall.args[0].query.includes('source=treeview') - ); - assert( - mockOpenTextDocument.firstCall.args[0].query.includes( - 'namespace=waffle.house' - ) - ); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'magna carta'); - - await vscode.commands.executeCommand('mdb.saveMongoDBDocument'); - - assert(mockDocument.name === 'something sweet'); - assert(mockDocument.time.$time === '12345'); - - const expectedMessage = - "The document was saved successfully to 'waffle.house'"; - - assert.strictEqual( - fakeShowInformationMessage.firstCall.args[0], - expectedMessage - ); - }); - - test('document opened from a tree has treeview source', async () => { - const mockDocument = { - _id: 'pancakes', - name: '', - time: { - $time: '12345', - }, - }; - const documentItem = new DocumentTreeItem( - mockDocument, - 'waffle.house', - 0, - {} as DataService, - () => Promise.resolve() - ); - - const mockFetchDocument = sinon.fake.resolves(null); - sinon.replace( - mdbTestExtension.testExtensionController._editorsController - ._mongoDBDocumentService, - 'fetchDocument', - mockFetchDocument - ); - - await vscode.commands.executeCommand( - 'mdb.openMongoDBDocumentFromTree', - documentItem - ); - - assert.strictEqual(mockFetchDocument.firstCall.args[0].source, 'treeview'); - }); - - test('document opened from playground results has treeview source', async () => { - const documentItem = { - source: 'playground', - line: 1, - documentId: '93333a0d-83f6-4e6f-a575-af7ea6187a4a', - namespace: 'db.coll', - connectionId: null, - }; - - const mockFetchDocument = sinon.fake.resolves(null); - sinon.replace( - mdbTestExtension.testExtensionController._editorsController - ._mongoDBDocumentService, - 'fetchDocument', - mockFetchDocument - ); - - await vscode.commands.executeCommand( - 'mdb.openMongoDBDocumentFromCodeLens', - documentItem - ); - - assert.strictEqual( - mockFetchDocument.firstCall.args[0].source, - 'playground' - ); - }); - - test('fetchDocument recieves treeview source if document opened from a tree', async () => { - const mockDocument = { - _id: 'pancakes', - name: '', - time: { - $time: '12345', - }, - }; - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - const mockGet = sinon.fake.returns('pancakes'); - sinon.replace( - mdbTestExtension.testExtensionController._editorsController - ._documentIdStore, - 'get', - mockGet - ); - sandbox.replaceGetter( - vscode.window, - 'activeTextEditor', - () => - ({ - document: { - uri: { - scheme: 'VIEW_DOCUMENT_SCHEME', - query: [ - 'namespace=waffle.house', - 'connectionId=tasty_sandwhich', - 'documentId=93333a0d-83f6-4e6f-a575-af7ea6187a4a', - 'source=treeview', - ].join('&'), + test('mdb.saveMongoDBDocument replaces a document with a treeview source', async () => { + const mockDocument = { + _id: 'pancakes', + name: '', + time: { + $time: '12345', + }, + }; + const mockGet = sinon.fake.returns('pancakes'); + sinon.replace( + mdbTestExtension.testExtensionController._editorsController + ._documentIdStore, + 'get', + mockGet + ); + sandbox.replaceGetter( + vscode.window, + 'activeTextEditor', + () => + ({ + document: { + uri: { + scheme: 'VIEW_DOCUMENT_SCHEME', + query: [ + 'namespace=waffle.house', + 'connectionId=tasty_sandwhich', + 'documentId=93333a0d-83f6-4e6f-a575-af7ea6187a4a', + 'source=treeview', + ].join('&'), + }, + getText: () => JSON.stringify(mockDocument), + save: () => {}, }, - getText: () => JSON.stringify(mockDocument), - save: () => {}, - }, - } as unknown as typeof vscode.window.activeTextEditor) - ); - - const mockReplaceDocument = sinon.fake.resolves(null); - sinon.replace( - mdbTestExtension.testExtensionController._editorsController - ._mongoDBDocumentService, - 'replaceDocument', - mockReplaceDocument - ); - - await vscode.commands.executeCommand('mdb.saveMongoDBDocument'); - - assert.strictEqual( - mockReplaceDocument.firstCall.args[0].source, - 'treeview' - ); - }); + } as unknown as typeof vscode.window.activeTextEditor) + ); - test('fetchDocument recieves playground source if document opened from playground results', async () => { - const mockDocument = { - _id: 'pancakes', - name: '', - time: { - $time: '12345', - }, - }; - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - const mockGet = sinon.fake.returns('pancakes'); - sinon.replace( - mdbTestExtension.testExtensionController._editorsController - ._documentIdStore, - 'get', - mockGet - ); + const mockReplaceDocument = sinon.fake.resolves(null); + sinon.replace( + mdbTestExtension.testExtensionController._editorsController + ._mongoDBDocumentService, + 'replaceDocument', + mockReplaceDocument + ); + await vscode.commands.executeCommand('mdb.saveMongoDBDocument'); + assert.strictEqual( + mockReplaceDocument.firstCall.args[0].source, + 'treeview' + ); + }); - sandbox.replaceGetter( - vscode.window, - 'activeTextEditor', - () => - ({ - document: { - uri: { - scheme: 'VIEW_DOCUMENT_SCHEME', - query: [ - 'namespace=waffle.house', - 'connectionId=tasty_sandwhich', - 'documentId=93333a0d-83f6-4e6f-a575-af7ea6187a4a', - 'source=playground', - ].join('&'), + test('mdb.saveMongoDBDocuments replaces a document with a playground source', async () => { + const mockDocument = { + _id: 'pancakes', + name: '', + time: { + $time: '12345', + }, + }; + const mockGet = sinon.fake.returns('pancakes'); + sinon.replace( + mdbTestExtension.testExtensionController._editorsController + ._documentIdStore, + 'get', + mockGet + ); + sandbox.replaceGetter( + vscode.window, + 'activeTextEditor', + () => + ({ + document: { + uri: { + scheme: 'VIEW_DOCUMENT_SCHEME', + query: [ + 'namespace=waffle.house', + 'connectionId=tasty_sandwhich', + 'documentId=93333a0d-83f6-4e6f-a575-af7ea6187a4a', + 'source=playground', + ].join('&'), + }, + getText: () => JSON.stringify(mockDocument), + save: () => {}, }, - getText: () => JSON.stringify(mockDocument), - save: () => {}, - }, - } as unknown as typeof vscode.window.activeTextEditor) - ); - - const mockReplaceDocument = sinon.fake.resolves(null); - sinon.replace( - mdbTestExtension.testExtensionController._editorsController - ._mongoDBDocumentService, - 'replaceDocument', - mockReplaceDocument - ); - - await vscode.commands.executeCommand('mdb.saveMongoDBDocument'); - - assert.strictEqual( - mockReplaceDocument.firstCall.args[0].source, - 'playground' - ); - }); - - test('mdb.searchForDocuments should create a MongoDB playground with search template', async () => { - const mockOpenTextDocument = sinon.fake.resolves('untitled'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); + } as unknown as typeof vscode.window.activeTextEditor) + ); - await vscode.commands.executeCommand('mdb.searchForDocuments', { - databaseName: 'dbbbbbName', - collectionName: 'colllllllllName', + const mockReplaceDocument = sinon.fake.resolves(null); + sinon.replace( + mdbTestExtension.testExtensionController._editorsController + ._mongoDBDocumentService, + 'replaceDocument', + mockReplaceDocument + ); + await vscode.commands.executeCommand('mdb.saveMongoDBDocument'); + assert.strictEqual( + mockReplaceDocument.firstCall.args[0].source, + 'playground' + ); }); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].language, - 'mongodb' - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes( - 'Search for documents in the current collection.' - ) - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes('dbbbbbName') - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes('colllllllllName') - ); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'untitled'); - }); - - test('mdb.createIndexFromTreeView should create a MongoDB playground with index template', async () => { - const mockOpenTextDocument = sinon.fake.resolves('untitled'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - await vscode.commands.executeCommand('mdb.createIndexFromTreeView', { - databaseName: 'dbbbbbName', - collectionName: 'colllllllllName', + test('mdb.runSelectedPlaygroundBlocks runs selected playgroundB blocks once', async () => { + const mockRunSelectedPlaygroundBlocks = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._playgroundController, + 'runSelectedPlaygroundBlocks', + mockRunSelectedPlaygroundBlocks + ); + await vscode.commands.executeCommand('mdb.runSelectedPlaygroundBlocks'); + assert( + mockRunSelectedPlaygroundBlocks.calledOnce, + 'Expected "runSelectedPlaygroundBlocks" to be called on the playground controller.' + ); }); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].language, - 'mongodb' - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes('dbbbbbName') - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes('colllllllllName') - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.includes( - 'Create a new index in the collection.' - ) - ); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'untitled'); - }); - - test('mdb.createPlayground should create a MongoDB playground with default template', async () => { - const mockOpenTextDocument = sinon.fake.resolves('untitled'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - const mockGetConfiguration = sinon.fake.returns({ - get: () => true, + test('mdb.runAllPlaygroundBlocks runs all playgroundB blocks once', async () => { + const mockRunAllPlaygroundBlocks = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._playgroundController, + 'runAllPlaygroundBlocks', + mockRunAllPlaygroundBlocks + ); + await vscode.commands.executeCommand('mdb.runAllPlaygroundBlocks'); + assert( + mockRunAllPlaygroundBlocks.calledOnce, + 'Expected "runAllPlaygroundBlocks" to be called on the playground controller.' + ); }); - sinon.replace(vscode.workspace, 'getConfiguration', mockGetConfiguration); - - await vscode.commands.executeCommand('mdb.createPlayground'); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].language, - 'mongodb' - ); - assert( - mockOpenTextDocument.firstCall.args[0].content.startsWith( - '// MongoDB Playground' - ) - ); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'untitled'); - }); - - test('mdb.createNewPlaygroundFromViewAction should create a MongoDB playground', async () => { - const mockOpenTextDocument = sinon.fake.resolves('untitled'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - await vscode.commands.executeCommand('mdb.createPlayground'); - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].language, - 'mongodb' - ); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'untitled'); - }); - - test('mdb.createPlayground command should create a MongoDB playground without template', async () => { - const mockOpenTextDocument = sinon.fake.resolves('untitled'); - sinon.replace(vscode.workspace, 'openTextDocument', mockOpenTextDocument); - - const mockShowTextDocument = sinon.fake(); - sinon.replace(vscode.window, 'showTextDocument', mockShowTextDocument); - - const mockGetConfiguration = sinon.fake.returns({ - get: () => false, + test('mdb.changeActiveConnection changes the active connection once', async () => { + const mockChangeActiveConnection = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._connectionController, + 'changeActiveConnection', + mockChangeActiveConnection + ); + await vscode.commands.executeCommand('mdb.changeActiveConnection'); + assert( + mockChangeActiveConnection.calledOnce, + 'Expected "changeActiveConnection" to be called on the playground controller.' + ); }); - sinon.replace(vscode.workspace, 'getConfiguration', mockGetConfiguration); - - await vscode.commands.executeCommand('mdb.createPlayground'); - - assert.strictEqual( - mockOpenTextDocument.firstCall.args[0].language, - 'mongodb' - ); - assert.strictEqual(mockOpenTextDocument.firstCall.args[0].content, ''); - assert.strictEqual(mockShowTextDocument.firstCall.args[0], 'untitled'); - }); - - test('mdb.runSelectedPlaygroundBlocks command should call runSelectedPlaygroundBlocks on the playground controller', async () => { - const mockRunSelectedPlaygroundBlocks = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._playgroundController, - 'runSelectedPlaygroundBlocks', - mockRunSelectedPlaygroundBlocks - ); - await vscode.commands.executeCommand('mdb.runSelectedPlaygroundBlocks'); - assert( - mockRunSelectedPlaygroundBlocks.calledOnce, - 'Expected "runSelectedPlaygroundBlocks" to be called on the playground controller.' - ); - }); - - test('mdb.runAllPlaygroundBlocks command should call runAllPlaygroundBlocks on the playground controller', async () => { - const mockRunAllPlaygroundBlocks = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._playgroundController, - 'runAllPlaygroundBlocks', - mockRunAllPlaygroundBlocks - ); - - await vscode.commands.executeCommand('mdb.runAllPlaygroundBlocks'); - assert( - mockRunAllPlaygroundBlocks.calledOnce, - 'Expected "runAllPlaygroundBlocks" to be called on the playground controller.' - ); - }); - - test('mdb.changeActiveConnection command should call changeActiveConnection on the playground controller', async () => { - const mockChangeActiveConnection = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._connectionController, - 'changeActiveConnection', - mockChangeActiveConnection - ); - - await vscode.commands.executeCommand('mdb.changeActiveConnection'); - assert( - mockChangeActiveConnection.calledOnce, - 'Expected "changeActiveConnection" to be called on the playground controller.' - ); - }); - - test('mdb.refreshPlaygrounds command should call refreshPlaygrounds on the playgrounds explorer controller', async () => { - const mockRefreshPlaygrounds = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._playgroundsExplorer, - 'refresh', - mockRefreshPlaygrounds - ); - - await vscode.commands.executeCommand('mdb.refreshPlaygrounds'); - assert( - mockRefreshPlaygrounds.calledOnce, - 'Expected "refreshPlaygrounds" to be called on the playground controller.' - ); - }); + test('mdb.refreshPlaygrounds refreshes the playgrounds explorer once', async () => { + const mockRefreshPlaygrounds = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._playgroundsExplorer, + 'refresh', + mockRefreshPlaygrounds + ); + await vscode.commands.executeCommand('mdb.refreshPlaygrounds'); + assert( + mockRefreshPlaygrounds.calledOnce, + 'Expected "refreshPlaygrounds" to be called on the playground controller.' + ); + }); - test("mdb.copyDocumentContentsFromTreeView should copy a document's content to the clipboard", async () => { - const mockDocument = { - _id: 'pancakes', - time: { - $time: '12345', - }, - }; - - let namespaceUsed = ''; - - const mockDataService = { - find: (namespace: string) => { - namespaceUsed = namespace; - return Promise.resolve([mockDocument]); - }, - } as Pick as unknown as DataService; - - const documentTreeItem = new DocumentTreeItem( - mockDocument, - 'waffle.house', - 0, - mockDataService, - () => Promise.resolve() - ); + test("mdb.copyDocumentContentsFromTreeView should copy a document's content to the clipboard", async () => { + const mockDocument = { + _id: 'pancakes', + time: { + $time: '12345', + }, + }; + let namespaceUsed = ''; - const mockCopyToClipboard = sinon.fake(); - sinon.replaceGetter(vscode.env, 'clipboard', () => ({ - writeText: mockCopyToClipboard, - readText: sinon.fake(), - })); + const findStub = sinon.stub(); + findStub.resolves([mockDocument]); - await vscode.commands.executeCommand( - 'mdb.copyDocumentContentsFromTreeView', - documentTreeItem - ); - assert.strictEqual(mockCopyToClipboard.called, true); - assert.strictEqual( - mockCopyToClipboard.firstCall.args[0], - `{ + const mockDataService = { + find: (namespace: string) => { + namespaceUsed = namespace; + return Promise.resolve([mockDocument]); + }, + } as Pick as unknown as DataService; + const documentTreeItem = new DocumentTreeItem( + mockDocument, + 'waffle.house', + 0, + mockDataService, + () => Promise.resolve() + ); + const mockCopyToClipboard = sinon.fake(); + sinon.replaceGetter(vscode.env, 'clipboard', () => ({ + writeText: mockCopyToClipboard, + readText: sinon.fake(), + })); + await vscode.commands.executeCommand( + 'mdb.copyDocumentContentsFromTreeView', + documentTreeItem + ); + assert.strictEqual(mockCopyToClipboard.called, true); + assert.strictEqual( + mockCopyToClipboard.firstCall.args[0], + `{ "_id": "pancakes", "time": { "$time": "12345" } }` - ); - assert.strictEqual(namespaceUsed, 'waffle.house'); - }); - - test("mdb.cloneDocumentFromTreeView event should open a playground with a document's content", async () => { - const mockDocument = { - _id: 'pancakes', - time: new Date('3001-01-01T05:00:00.000Z'), - objectIdField: new ObjectId('57e193d7a9cc81b4027498b2'), - }; - - let namespaceUsed = ''; - - const mockDataService = { - find: (namespace: string) => { - namespaceUsed = namespace; - return Promise.resolve([mockDocument]); - }, - } as Pick as unknown as DataService; - - const documentTreeItem = new DocumentTreeItem( - mockDocument, - 'waffle.house', - 0, - mockDataService, - () => Promise.resolve() - ); - - const mockCreatePlaygroundForCloneDocument = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._playgroundController, - 'createPlaygroundForCloneDocument', - mockCreatePlaygroundForCloneDocument - ); + ); + assert.strictEqual(namespaceUsed, 'waffle.house'); + }); - await vscode.commands.executeCommand( - 'mdb.cloneDocumentFromTreeView', - documentTreeItem - ); - assert.strictEqual(mockCreatePlaygroundForCloneDocument.calledOnce, true); - assert.strictEqual( - mockCreatePlaygroundForCloneDocument.firstCall.args[0], - `{ + test("mdb.cloneDocumentFromTreeView opens a playground with a document's content", async () => { + const mockDocument = { + _id: 'pancakes', + time: new Date('3001-01-01T05:00:00.000Z'), + objectIdField: new ObjectId('57e193d7a9cc81b4027498b2'), + }; + let namespaceUsed = ''; + const mockDataService = { + find: (namespace: string) => { + namespaceUsed = namespace; + return Promise.resolve([mockDocument]); + }, + } as unknown as DataService; + const documentTreeItem = new DocumentTreeItem( + mockDocument, + 'waffle.house', + 0, + mockDataService, + () => Promise.resolve() + ); + const mockCreatePlaygroundForCloneDocument = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._playgroundController, + 'createPlaygroundForCloneDocument', + mockCreatePlaygroundForCloneDocument + ); + await vscode.commands.executeCommand( + 'mdb.cloneDocumentFromTreeView', + documentTreeItem + ); + assert.strictEqual(mockCreatePlaygroundForCloneDocument.calledOnce, true); + assert.strictEqual( + mockCreatePlaygroundForCloneDocument.firstCall.args[0], + `{ _id: 'pancakes', time: ISODate('3001-01-01T05:00:00.000Z'), objectIdField: ObjectId('57e193d7a9cc81b4027498b2') }` - ); - assert.strictEqual( - mockCreatePlaygroundForCloneDocument.firstCall.args[1], - 'waffle' - ); - assert.strictEqual( - mockCreatePlaygroundForCloneDocument.firstCall.args[2], - 'house' - ); - assert.strictEqual(namespaceUsed, 'waffle.house'); - }); + ); + assert.strictEqual( + mockCreatePlaygroundForCloneDocument.firstCall.args[1], + 'waffle' + ); + assert.strictEqual( + mockCreatePlaygroundForCloneDocument.firstCall.args[2], + 'house' + ); + assert.strictEqual(namespaceUsed, 'waffle.house'); + }); - test('mdb.insertDocumentFromTreeView event should open a playground with an insert document template', async () => { - const collectionTreeItem = new CollectionTreeItem( - { - name: 'pineapple', - type: CollectionTypes.collection, - }, - 'plants', - {}, - false, - false, - null - ); + test('mdb.insertDocumentFromTreeView opens a playground with an insert document template', async () => { + const collectionTreeItem = new CollectionTreeItem( + { + name: 'pineapple', + type: CollectionTypes.collection, + }, + 'plants', + {}, + false, + false, + null + ); + const mockCreatePlaygroundForInsertDocument = sinon.fake(); + sinon.replace( + mdbTestExtension.testExtensionController._playgroundController, + 'createPlaygroundForInsertDocument', + mockCreatePlaygroundForInsertDocument + ); + await vscode.commands.executeCommand( + 'mdb.insertDocumentFromTreeView', + collectionTreeItem + ); + assert.strictEqual( + mockCreatePlaygroundForInsertDocument.calledOnce, + true + ); + assert.strictEqual( + mockCreatePlaygroundForInsertDocument.firstCall.args[0], + 'plants' + ); + assert.strictEqual( + mockCreatePlaygroundForInsertDocument.firstCall.args[1], + 'pineapple' + ); + }); - const mockCreatePlaygroundForInsertDocument = sinon.fake(); - sinon.replace( - mdbTestExtension.testExtensionController._playgroundController, - 'createPlaygroundForInsertDocument', - mockCreatePlaygroundForInsertDocument - ); + test('mdb.deleteDocumentFromTreeView deletes a document when the confirmation is cancelled', async () => { + const mockDocument = { + _id: 'pancakes', + time: { + $time: '12345', + }, + }; + let calledDelete = false; + const mockDataService = { + deleteOne: ( + namespace: string, + _id: any, + options: object, + callback: ( + error: Error | undefined, + result: { deletedCount: number } + ) => void + ) => { + calledDelete = true; + callback(undefined, { + deletedCount: 1, + }); + }, + } as Pick as unknown as DataService; + const documentTreeItem = new DocumentTreeItem( + mockDocument, + 'waffle.house', + 0, + mockDataService, + () => Promise.resolve() + ); + const result = await vscode.commands.executeCommand( + 'mdb.deleteDocumentFromTreeView', + documentTreeItem + ); + assert.strictEqual(result, false); + assert.strictEqual(calledDelete, false); + }); - await vscode.commands.executeCommand( - 'mdb.insertDocumentFromTreeView', - collectionTreeItem - ); - assert.strictEqual(mockCreatePlaygroundForInsertDocument.calledOnce, true); - assert.strictEqual( - mockCreatePlaygroundForInsertDocument.firstCall.args[0], - 'plants' - ); - assert.strictEqual( - mockCreatePlaygroundForInsertDocument.firstCall.args[1], - 'pineapple' - ); - }); + test('mdb.deleteDocumentFromTreeView deletes a document after confirmation', async () => { + fakeShowInformationMessage.resolves('Yes'); - test('mdb.deleteDocumentFromTreeView should not delete a document when the confirmation is cancelled', async () => { - const mockDocument = { - _id: 'pancakes', - time: { - $time: '12345', - }, - }; - - let calledDelete = false; - - const mockDataService = { - deleteOne: ( - namespace: string, - _id: any, - options: object, - callback: ( - error: Error | undefined, - result: { deletedCount: number } - ) => void - ) => { - calledDelete = true; - callback(undefined, { - deletedCount: 1, + const mockDocument = { + _id: 'pancakes', + time: { + $time: '12345', + }, + }; + let namespaceUsed = ''; + let _idUsed; + const mockDataService = { + deleteOne: ( + namespace: string, + query: any, + options: object, + callback: ( + error: Error | undefined, + result: { deletedCount: number } + ) => void + ) => { + _idUsed = query; + namespaceUsed = namespace; + callback(undefined, { + deletedCount: 1, + }); + }, + } as Pick as unknown as DataService; + const documentTreeItem = new DocumentTreeItem( + mockDocument, + 'waffle.house', + 0, + mockDataService, + () => Promise.resolve() + ); + const result = await vscode.commands.executeCommand( + 'mdb.deleteDocumentFromTreeView', + documentTreeItem + ); + assert.deepStrictEqual(_idUsed, { + _id: 'pancakes', + }); + assert.strictEqual(namespaceUsed, 'waffle.house'); + assert.strictEqual(result, true); + }); + + suite( + 'when a user hasnt been shown the initial overview page yet and they have no connections saved', + () => { + let mockVSCodeExecuteCommand: SinonSpy; + let mockStorageControllerUpdate: SinonSpy; + + beforeEach(() => { + mockVSCodeExecuteCommand = sinon.fake.resolves(undefined); + sinon.replace( + vscode.commands, + 'executeCommand', + mockVSCodeExecuteCommand + ); + sinon.replace( + mdbTestExtension.testExtensionController._storageController, + 'get', + sinon.fake.returns(false) + ); + sinon.replace( + mdbTestExtension.testExtensionController._storageController, + 'hasSavedConnections', + sinon.fake.returns(false) + ); + + mockStorageControllerUpdate = sinon.fake.resolves(undefined); + sinon.replace( + mdbTestExtension.testExtensionController._storageController, + 'update', + mockStorageControllerUpdate + ); + + void mdbTestExtension.testExtensionController.showOverviewPageIfRecentlyInstalled(); }); - }, - } as Pick as unknown as DataService; - - const documentTreeItem = new DocumentTreeItem( - mockDocument, - 'waffle.house', - 0, - mockDataService, - () => Promise.resolve() - ); - const result = await vscode.commands.executeCommand( - 'mdb.deleteDocumentFromTreeView', - documentTreeItem - ); + afterEach(() => { + sinon.restore(); + }); - assert.strictEqual(result, false); - assert.strictEqual(calledDelete, false); - }); + test('they are shown the overview page', () => { + assert(mockVSCodeExecuteCommand.called); + assert.strictEqual( + mockVSCodeExecuteCommand.firstCall.args[0], + 'mdb.openOverviewPage' + ); + assert.strictEqual( + mockVSCodeExecuteCommand.firstCall.args[0], + EXTENSION_COMMANDS.MDB_OPEN_OVERVIEW_PAGE + ); + }); + + test("it sets that they've been shown the overview page", () => { + assert(mockStorageControllerUpdate.called); + assert.strictEqual( + mockStorageControllerUpdate.firstCall.args[0], + StorageVariables.GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW + ); + assert.strictEqual( + mockStorageControllerUpdate.firstCall.args[0], + 'GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW' + ); + assert.strictEqual( + mockStorageControllerUpdate.firstCall.args[1], + true + ); + }); + } + ); + + suite( + 'when a user hasnt been shown the initial overview page yet and they have connections saved', + () => { + let mockVSCodeExecuteCommand: SinonSpy; + let mockStorageControllerUpdate: SinonSpy; + + beforeEach(() => { + mockVSCodeExecuteCommand = sinon.fake.resolves(undefined); + sinon.replace( + vscode.commands, + 'executeCommand', + mockVSCodeExecuteCommand + ); + sinon.replace( + mdbTestExtension.testExtensionController._storageController, + 'get', + sinon.fake.returns(undefined) + ); + sinon.replace( + mdbTestExtension.testExtensionController._storageController, + 'hasSavedConnections', + sinon.fake.returns(true) + ); + mockStorageControllerUpdate = sinon.fake.resolves(undefined); + sinon.replace( + mdbTestExtension.testExtensionController._storageController, + 'update', + mockStorageControllerUpdate + ); + + void mdbTestExtension.testExtensionController.showOverviewPageIfRecentlyInstalled(); + }); - test('mdb.deleteDocumentFromTreeView deletes a document after confirmation', async () => { - fakeShowInformationMessage.resolves('Yes'); - - const mockDocument = { - _id: 'pancakes', - time: { - $time: '12345', - }, - }; - - let namespaceUsed = ''; - let _idUsed; - - const mockDataService = { - deleteOne: ( - namespace: string, - query: any, - options: object, - callback: ( - error: Error | undefined, - result: { deletedCount: number } - ) => void - ) => { - _idUsed = query; - namespaceUsed = namespace; - callback(undefined, { - deletedCount: 1, + test('they are not shown the overview page', () => { + assert(!mockVSCodeExecuteCommand.called); }); - }, - } as Pick as unknown as DataService; - - const documentTreeItem = new DocumentTreeItem( - mockDocument, - 'waffle.house', - 0, - mockDataService, - () => Promise.resolve() - ); - const result = await vscode.commands.executeCommand( - 'mdb.deleteDocumentFromTreeView', - documentTreeItem + test("it sets that they've been shown the overview page", () => { + assert(mockStorageControllerUpdate.called); + assert.strictEqual( + mockStorageControllerUpdate.firstCall.args[0], + StorageVariables.GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW + ); + assert.strictEqual( + mockStorageControllerUpdate.firstCall.args[0], + 'GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW' + ); + assert.strictEqual( + mockStorageControllerUpdate.firstCall.args[1], + true + ); + }); + } ); - assert.deepStrictEqual(_idUsed, { - _id: 'pancakes', - }); - assert.strictEqual(namespaceUsed, 'waffle.house'); - assert.strictEqual(result, true); - }); - suite( - 'when a user hasnt been shown the initial overview page yet and they have no connections saved', - () => { + suite('when a user has been shown the initial overview page', () => { let mockVSCodeExecuteCommand: SinonSpy; - let mockStorageControllerUpdate: SinonSpy; beforeEach(() => { - mockVSCodeExecuteCommand = sinon.fake.resolves(undefined); - sinon.replace( - vscode.commands, - 'executeCommand', - mockVSCodeExecuteCommand - ); sinon.replace( mdbTestExtension.testExtensionController._storageController, 'get', - sinon.fake.returns(false) - ); - sinon.replace( - mdbTestExtension.testExtensionController._storageController, - 'hasSavedConnections', - sinon.fake.returns(false) - ); - - mockStorageControllerUpdate = sinon.fake.resolves(undefined); - sinon.replace( - mdbTestExtension.testExtensionController._storageController, - 'update', - mockStorageControllerUpdate - ); - - void mdbTestExtension.testExtensionController.showOverviewPageIfRecentlyInstalled(); - }); - - afterEach(() => { - sinon.restore(); - }); - - test('they are shown the overview page', () => { - assert(mockVSCodeExecuteCommand.called); - assert( - mockVSCodeExecuteCommand.firstCall.args[0] === 'mdb.openOverviewPage' - ); - assert( - mockVSCodeExecuteCommand.firstCall.args[0] === - EXTENSION_COMMANDS.MDB_OPEN_OVERVIEW_PAGE - ); - }); - - test("it sets that they've been shown the overview page", () => { - assert(mockStorageControllerUpdate.called); - assert( - mockStorageControllerUpdate.firstCall.args[0] === - StorageVariables.GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW - ); - assert( - mockStorageControllerUpdate.firstCall.args[0] === - 'GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW' + sinon.fake.returns(true) ); - assert(mockStorageControllerUpdate.firstCall.args[1] === true); - }); - } - ); - - suite( - 'when a user hasnt been shown the initial overview page yet and they have connections saved', - () => { - let mockVSCodeExecuteCommand: SinonSpy; - let mockStorageControllerUpdate: SinonSpy; - - beforeEach(() => { mockVSCodeExecuteCommand = sinon.fake.resolves(undefined); sinon.replace( vscode.commands, 'executeCommand', mockVSCodeExecuteCommand ); - sinon.replace( - mdbTestExtension.testExtensionController._storageController, - 'get', - sinon.fake.returns(undefined) - ); - - sinon.replace( - mdbTestExtension.testExtensionController._storageController, - 'hasSavedConnections', - sinon.fake.returns(true) - ); - - mockStorageControllerUpdate = sinon.fake.resolves(undefined); - sinon.replace( - mdbTestExtension.testExtensionController._storageController, - 'update', - mockStorageControllerUpdate - ); void mdbTestExtension.testExtensionController.showOverviewPageIfRecentlyInstalled(); }); @@ -1876,44 +1705,6 @@ suite('MDBExtensionController Test Suite', function () { test('they are not shown the overview page', () => { assert(!mockVSCodeExecuteCommand.called); }); - - test("it sets that they've been shown the overview page", () => { - assert(mockStorageControllerUpdate.called); - assert( - mockStorageControllerUpdate.firstCall.args[0] === - StorageVariables.GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW - ); - assert( - mockStorageControllerUpdate.firstCall.args[0] === - 'GLOBAL_HAS_BEEN_SHOWN_INITIAL_VIEW' - ); - assert(mockStorageControllerUpdate.firstCall.args[1] === true); - }); - } - ); - - suite('when a user has been shown the initial overview page', () => { - let mockVSCodeExecuteCommand: SinonSpy; - - beforeEach(() => { - sinon.replace( - mdbTestExtension.testExtensionController._storageController, - 'get', - sinon.fake.returns(true) - ); - - mockVSCodeExecuteCommand = sinon.fake.resolves(undefined); - sinon.replace( - vscode.commands, - 'executeCommand', - mockVSCodeExecuteCommand - ); - - void mdbTestExtension.testExtensionController.showOverviewPageIfRecentlyInstalled(); - }); - - test('they are not shown the overview page', () => { - assert(!mockVSCodeExecuteCommand.called); }); }); }); diff --git a/src/test/suite/telemetry/connectionTelemetry.test.ts b/src/test/suite/telemetry/connectionTelemetry.test.ts index 36cf9131e..5af6a48f3 100644 --- a/src/test/suite/telemetry/connectionTelemetry.test.ts +++ b/src/test/suite/telemetry/connectionTelemetry.test.ts @@ -1,18 +1,19 @@ import { before, after, beforeEach, afterEach } from 'mocha'; import { connect } from 'mongodb-data-service'; -import type { DataService } from 'mongodb-data-service'; import { expect } from 'chai'; import sinon from 'sinon'; +import type { DataService } from 'mongodb-data-service'; + +import getCloudInfoModule from 'mongodb-cloud-info'; import { ConnectionTypes } from '../../../connectionController'; -import { getConnectionTelemetryProperties } from '../../../telemetry/connectionTelemetry'; +import * as connectionTelemetry from '../../../telemetry/connectionTelemetry'; const TEST_DATABASE_URI = 'mongodb://localhost:27018'; suite('ConnectionTelemetry Controller Test Suite', function () { - this.timeout(8000); - - suite('with mock data service', () => { + suite('with mock data service', function () { + this.timeout(8000); let mockDataService: DataService; before(() => { @@ -38,6 +39,8 @@ suite('ConnectionTelemetry Controller Test Suite', function () { DataService, 'getConnectionString' | 'instance' > as unknown as DataService; + + sinon.stub(getCloudInfoModule, 'getCloudInfo').resolves({}); }); after(() => { @@ -45,10 +48,11 @@ suite('ConnectionTelemetry Controller Test Suite', function () { }); test('it returns is_used_connect_screen true when the connection type is form', async () => { - const instanceTelemetry = await getConnectionTelemetryProperties( - mockDataService, - ConnectionTypes.CONNECTION_FORM - ); + const instanceTelemetry = + await connectionTelemetry.getConnectionTelemetryProperties( + mockDataService, + ConnectionTypes.CONNECTION_FORM + ); expect(instanceTelemetry.is_used_connect_screen).to.equal(true); expect(instanceTelemetry.is_used_command_palette).to.equal(false); @@ -56,10 +60,11 @@ suite('ConnectionTelemetry Controller Test Suite', function () { }); test('it returns is_used_command_palette true when the connection type is string', async () => { - const instanceTelemetry = await getConnectionTelemetryProperties( - mockDataService, - ConnectionTypes.CONNECTION_STRING - ); + const instanceTelemetry = + await connectionTelemetry.getConnectionTelemetryProperties( + mockDataService, + ConnectionTypes.CONNECTION_STRING + ); expect(instanceTelemetry.is_used_connect_screen).to.equal(false); expect(instanceTelemetry.is_used_command_palette).to.equal(true); @@ -67,10 +72,11 @@ suite('ConnectionTelemetry Controller Test Suite', function () { }); test('it returns is_used_saved_connection true when the connection type is id', async () => { - const instanceTelemetry = await getConnectionTelemetryProperties( - mockDataService, - ConnectionTypes.CONNECTION_ID - ); + const instanceTelemetry = + await connectionTelemetry.getConnectionTelemetryProperties( + mockDataService, + ConnectionTypes.CONNECTION_ID + ); expect(instanceTelemetry.is_used_connect_screen).to.equal(false); expect(instanceTelemetry.is_used_command_palette).to.equal(false); @@ -78,34 +84,38 @@ suite('ConnectionTelemetry Controller Test Suite', function () { }); test('it has is_localhost false for a remote connection', async () => { - const instanceTelemetry = await getConnectionTelemetryProperties( - mockDataService, - ConnectionTypes.CONNECTION_STRING - ); + const instanceTelemetry = + await connectionTelemetry.getConnectionTelemetryProperties( + mockDataService, + ConnectionTypes.CONNECTION_STRING + ); expect(instanceTelemetry.is_localhost).to.equal(false); }); test('it has a default is atlas false', async () => { - const instanceTelemetry = await getConnectionTelemetryProperties( - mockDataService, - ConnectionTypes.CONNECTION_STRING - ); + const instanceTelemetry = + await connectionTelemetry.getConnectionTelemetryProperties( + mockDataService, + ConnectionTypes.CONNECTION_STRING + ); expect(instanceTelemetry.is_atlas).to.equal(false); }); test('it has a default driver auth mechanism undefined', async () => { - const instanceTelemetry = await getConnectionTelemetryProperties( - mockDataService, - ConnectionTypes.CONNECTION_STRING - ); + const instanceTelemetry = + await connectionTelemetry.getConnectionTelemetryProperties( + mockDataService, + ConnectionTypes.CONNECTION_STRING + ); expect(instanceTelemetry.auth_strategy).to.equal('DEFAULT'); }); }); - suite('with live connection', () => { + suite('with live connection', function () { + this.timeout(20000); let dataServ; beforeEach(async () => { @@ -118,10 +128,11 @@ suite('ConnectionTelemetry Controller Test Suite', function () { }); test('track new connection event fetches the connection instance information', async () => { - const instanceTelemetry = await getConnectionTelemetryProperties( - dataServ, - ConnectionTypes.CONNECTION_STRING - ); + const instanceTelemetry = + await connectionTelemetry.getConnectionTelemetryProperties( + dataServ, + ConnectionTypes.CONNECTION_STRING + ); expect(instanceTelemetry.is_localhost).to.equal(true); expect(instanceTelemetry.is_atlas).to.equal(false); diff --git a/src/test/suite/telemetry/telemetryService.test.ts b/src/test/suite/telemetry/telemetryService.test.ts index f3d1ea262..59af504ff 100644 --- a/src/test/suite/telemetry/telemetryService.test.ts +++ b/src/test/suite/telemetry/telemetryService.test.ts @@ -2,7 +2,6 @@ import * as vscode from 'vscode'; import path from 'path'; import { afterEach, beforeEach } from 'mocha'; import chai from 'chai'; -import { connect } from 'mongodb-data-service'; import type { DataService } from 'mongodb-data-service'; import { config } from 'dotenv'; import { resolve } from 'path'; @@ -14,7 +13,6 @@ import { ConnectionTypes } from '../../../connectionController'; import { DocumentSource } from '../../../documentSource'; import { ExportToLanguageMode } from '../../../types/playgroundType'; import { mdbTestExtension } from '../stubbableMdbExtension'; -import { NewConnectionTelemetryEventProperties } from '../../../telemetry/connectionTelemetry'; import { SegmentProperties, TelemetryEventTypes, @@ -23,8 +21,6 @@ import { const expect = chai.expect; const { version } = require('../../../../package.json'); -const TEST_DATABASE_URI = 'mongodb://localhost:27018'; - chai.use(sinonChai); config({ path: resolve(__dirname, '../../../../.env') }); @@ -64,12 +60,14 @@ suite('Telemetry Controller Test Suite', () => { mockTrackCommandRun ); sinon.replace( - mdbTestExtension.testExtensionController._telemetryService, + mdbTestExtension.testExtensionController._playgroundController + ._telemetryService, 'trackPlaygroundCodeExecuted', mockTrackPlaygroundCodeExecuted ); sinon.replace( - mdbTestExtension.testExtensionController._telemetryService, + mdbTestExtension.testExtensionController._playgroundController + ._telemetryService, 'trackPlaygroundLoaded', mockTrackPlaygroundLoadedMethod ); @@ -322,7 +320,7 @@ suite('Telemetry Controller Test Suite', () => { const mode = ExportToLanguageMode.QUERY; const language = 'python'; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.mode = + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = mode; mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider._exportToLanguageAddons = { @@ -365,7 +363,7 @@ suite('Telemetry Controller Test Suite', () => { const mode = ExportToLanguageMode.AGGREGATION; const language = 'java'; - mdbTestExtension.testExtensionController._playgroundController._codeActionProvider.mode = + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = mode; mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider._exportToLanguageAddons = { @@ -391,47 +389,6 @@ suite('Telemetry Controller Test Suite', () => { }); }); - suite('with active connection', function () { - this.timeout(5000); - - let dataServ; - beforeEach(async () => { - try { - dataServ = await connect({ connectionString: TEST_DATABASE_URI }); - } catch (error) { - expect(error).to.be.undefined; - } - }); - - afterEach(async () => { - sinon.restore(); - await dataServ.disconnect(); - }); - - test('track new connection event fetches the connection instance information', async () => { - sinon.replace(testTelemetryService, 'track', mockTrack); - sinon.replace( - testTelemetryService, - '_isTelemetryFeatureEnabled', - () => true - ); - await mdbTestExtension.testExtensionController._telemetryService.trackNewConnection( - dataServ, - ConnectionTypes.CONNECTION_STRING - ); - - expect(mockTrack.firstCall.args[0]).to.equal('New Connection'); - const instanceTelemetry: NewConnectionTelemetryEventProperties = - mockTrack.firstCall.args[1]; - expect(instanceTelemetry.is_localhost).to.equal(true); - expect(instanceTelemetry.is_atlas).to.equal(false); - expect(instanceTelemetry.is_used_connect_screen).to.equal(false); - expect(instanceTelemetry.is_used_command_palette).to.equal(true); - expect(instanceTelemetry.is_used_saved_connection).to.equal(false); - expect(instanceTelemetry.is_genuine).to.equal(true); - }); - }); - suite('prepare playground result types', () => { test('convert AggregationCursor shellApiType to aggregation telemetry type', () => { const res = { diff --git a/src/utils/playground.ts b/src/utils/playground.ts new file mode 100644 index 000000000..576584965 --- /dev/null +++ b/src/utils/playground.ts @@ -0,0 +1,118 @@ +import * as vscode from 'vscode'; +import micromatch from 'micromatch'; +import * as fs from 'fs'; +import * as path from 'path'; + +import { createLogger } from '../logging'; + +const log = createLogger('playground utils'); + +export class FileStat implements vscode.FileStat { + constructor(private fsStat: fs.Stats) {} + + get type(): vscode.FileType { + if (this.fsStat.isFile()) { + return vscode.FileType.File; + } + if (this.fsStat.isDirectory()) { + return vscode.FileType.Directory; + } + if (this.fsStat.isSymbolicLink()) { + return vscode.FileType.SymbolicLink; + } + + return vscode.FileType.Unknown; + } + + get isFile(): boolean | undefined { + return this.fsStat.isFile(); + } + + get isDirectory(): boolean | undefined { + return this.fsStat.isDirectory(); + } + + get isSymbolicLink(): boolean | undefined { + return this.fsStat.isSymbolicLink(); + } + + get size(): number { + return this.fsStat.size; + } + + get ctime(): number { + return this.fsStat.ctime.getTime(); + } + + get mtime(): number { + return this.fsStat.mtime.getTime(); + } +} + +const getFileNames = (filePath: string): Promise => { + return fs.promises.readdir(filePath); +}; + +const getStat = async (filePath: string): Promise => { + return new FileStat(await stat(filePath)); +}; + +const stat = (filePath: string): Promise => { + return fs.promises.lstat(filePath); +}; + +export const isPlayground = (fileUri?: vscode.Uri) => { + if (!fileUri) { + return false; + } + + const fileNameParts = fileUri.fsPath.split('.'); + + if (fileNameParts.length < 2) { + return false; + } + + // The default playgrounds extension is `.mongodb.js`. + const extension = fileNameParts[fileNameParts.length - 1]; + const secondaryExtension = fileNameParts[fileNameParts.length - 2]; + + return ( + extension === 'mongodb' || + (extension === 'js' && secondaryExtension === 'mongodb') + ); +}; + +export const getPlaygrounds = async ({ + fsPath, + excludeFromPlaygroundsSearch, +}: { + fsPath: string; + excludeFromPlaygroundsSearch?: string[]; +}): Promise<{ name: string; path: string }[]> => { + const result: { name: string; path: string }[] = []; + const fileNames = await getFileNames(fsPath); + for (const fileName of fileNames) { + try { + const stat = await getStat(path.join(fsPath, fileName)); + const fileUri = vscode.Uri.file(path.join(fsPath, fileName)); + + if (stat.type === vscode.FileType.File && isPlayground(fileUri)) { + result.push({ name: fileName, path: fileUri.fsPath }); + } else if ( + stat.type === vscode.FileType.Directory && + (!excludeFromPlaygroundsSearch || + !micromatch.isMatch(fileName, excludeFromPlaygroundsSearch)) + ) { + const playgrounds = await getPlaygrounds({ + fsPath: fileUri.fsPath, + excludeFromPlaygroundsSearch, + }); + result.push(...playgrounds); + } + } catch (error) { + log.error('Get playgrounds recursively from the workspace error', error); + } + } + + return result; +}; diff --git a/syntaxes/mongodb.tmLanguage.json b/syntaxes/mongodb.tmLanguage.json deleted file mode 100644 index f8cc8b640..000000000 --- a/syntaxes/mongodb.tmLanguage.json +++ /dev/null @@ -1,7263 +0,0 @@ -{ - "name": "MongoDB", - "uuid": "ef98eb90-bf9b-11e4-bb52-0800200c9a66", - "scopeName": "source.mongodb", - "fileTypes": [ - "mongodb" - ], - "patterns": [ - { - "include": "#directives" - }, - { - "include": "#statements" - }, - { - "name": "comment.line.shebang.mongodb", - "match": "\\A(#!).*(?=$)", - "captures": { - "1": { - "name": "punctuation.definition.comment.mongodb" - } - } - } - ], - "repository": { - "statements": { - "patterns": [ - { - "include": "#declaration" - }, - { - "include": "#control-statement" - }, - { - "include": "#after-operator-block-as-object-literal" - }, - { - "include": "#decl-block" - }, - { - "include": "#label" - }, - { - "include": "#expression" - }, - { - "include": "#punctuation-semicolon" - }, - { - "include": "#string" - }, - { - "include": "#comment" - } - ] - }, - "declaration": { - "patterns": [ - { - "include": "#decorator" - }, - { - "include": "#var-expr" - }, - { - "include": "#function-declaration" - }, - { - "include": "#class-declaration" - }, - { - "include": "#interface-declaration" - }, - { - "include": "#enum-declaration" - }, - { - "include": "#namespace-declaration" - }, - { - "include": "#type-alias-declaration" - }, - { - "include": "#import-equals-declaration" - }, - { - "include": "#import-declaration" - }, - { - "include": "#export-declaration" - }, - { - "name": "storage.modifier.mongodb", - "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.mongodb entity.name.function.mongodb" - }, - "2": { - "name": "keyword.operator.definiteassignment.mongodb" - } - }, - "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.mongodb variable.other.constant.mongodb entity.name.function.mongodb" - } - }, - "end": "(?=$|^|[;,=}]|((?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "1": { - "name": "storage.modifier.mongodb" - }, - "2": { - "name": "keyword.operator.rest.mongodb" - }, - "3": { - "name": "entity.name.function.mongodb variable.language.this.mongodb" - }, - "4": { - "name": "entity.name.function.mongodb" - }, - "5": { - "name": "keyword.operator.optional.mongodb" - } - } - }, - { - "match": "(?x)(?:(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "1": { - "name": "meta.definition.property.mongodb entity.name.function.mongodb" - }, - "2": { - "name": "keyword.operator.optional.mongodb" - }, - "3": { - "name": "keyword.operator.definiteassignment.mongodb" - } - } - }, - { - "name": "meta.definition.property.mongodb variable.object.property.mongodb", - "match": "\\#?[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.mongodb", - "match": "\\?" - }, - { - "name": "keyword.operator.definiteassignment.mongodb", - "match": "\\!" - } - ] - }, - "variable-initializer": { - "patterns": [ - { - "begin": "(?\\s*$)", - "beginCaptures": { - "1": { - "name": "keyword.operator.assignment.mongodb" - } - }, - "end": "(?=$|^|[,);}\\]]|((?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", - "beginCaptures": { - "1": { - "name": "storage.modifier.mongodb" - }, - "2": { - "name": "storage.modifier.mongodb" - }, - "3": { - "name": "storage.modifier.async.mongodb" - }, - "4": { - "name": "keyword.operator.new.mongodb" - }, - "5": { - "name": "keyword.generator.asterisk.mongodb" - } - }, - "end": "(?=\\}|;|,|$)|(?<=\\})", - "patterns": [ - { - "include": "#method-declaration-name" - }, - { - "include": "#function-body" - } - ] - }, - { - "name": "meta.method.declaration.mongodb", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", - "beginCaptures": { - "1": { - "name": "storage.modifier.mongodb" - }, - "2": { - "name": "storage.modifier.mongodb" - }, - "3": { - "name": "storage.modifier.async.mongodb" - }, - "4": { - "name": "storage.type.property.mongodb" - }, - "5": { - "name": "keyword.generator.asterisk.mongodb" - } - }, - "end": "(?=\\}|;|,|$)|(?<=\\})", - "patterns": [ - { - "include": "#method-declaration-name" - }, - { - "include": "#function-body" - } - ] - } - ] - }, - "object-literal-method-declaration": { - "name": "meta.method.declaration.mongodb", - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - }, - "2": { - "name": "storage.type.property.mongodb" - }, - "3": { - "name": "keyword.generator.asterisk.mongodb" - } - }, - "end": "(?=\\}|;|,)|(?<=\\})", - "patterns": [ - { - "include": "#method-declaration-name" - }, - { - "include": "#function-body" - }, - { - "begin": "(?x)(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?[\\(])", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - }, - "2": { - "name": "storage.type.property.mongodb" - }, - "3": { - "name": "keyword.generator.asterisk.mongodb" - } - }, - "end": "(?=\\(|\\<)", - "patterns": [ - { - "include": "#method-declaration-name" - } - ] - } - ] - }, - "method-declaration-name": { - "begin": "(?x)(?=((\\b(?)", - "captures": { - "1": { - "name": "storage.modifier.async.mongodb" - }, - "2": { - "name": "variable.parameter.mongodb" - } - } - }, - { - "name": "meta.arrow.mongodb", - "begin": "(?x) (?:\n (? is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - } - }, - "end": "(?==>|\\{|(^\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\s+))", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type-parameters" - }, - { - "include": "#function-parameters" - }, - { - "include": "#arrow-return-type" - }, - { - "include": "#possibly-arrow-return-type" - } - ] - }, - { - "name": "meta.arrow.mongodb", - "begin": "=>", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.mongodb" - } - }, - "end": "((?<=\\}|\\S)(?)|((?!\\{)(?=\\S)))(?!\\/[\\/\\*])", - "patterns": [ - { - "include": "#single-line-comment-consuming-line-ending" - }, - { - "include": "#decl-block" - }, - { - "include": "#expression" - } - ] - } - ] - }, - "indexer-declaration": { - "name": "meta.indexer.declaration.mongodb", - "begin": "(?:(?]|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^yield|[^\\._$[:alnum:]]yield|^throw|[^\\._$[:alnum:]]throw|^in|[^\\._$[:alnum:]]in|^of|[^\\._$[:alnum:]]of|^typeof|[^\\._$[:alnum:]]typeof|&&|\\|\\||\\*)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.mongodb" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.mongodb" - } - }, - "patterns": [ - { - "include": "#object-member" - } - ] - }, - "object-literal": { - "name": "meta.objectliteral.mongodb", - "begin": "\\{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.mongodb" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.mongodb" - } - }, - "patterns": [ - { - "include": "#object-member" - } - ] - }, - "object-member": { - "patterns": [ - { - "name": "meta.object.member.mongodb", - "match": "\\$undefined\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.undefined.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$timestamp\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.timestamp.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$regularExpression\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.regularExpression.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$regex\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.regex.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$oid\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.oid.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$numberLong\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.numberLong.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$numberInt\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.numberInt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$numberDouble\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.numberDouble.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$numberDecimal\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.numberDecimal.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$minKey\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.minKey.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$maxKey\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.maxKey.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$date\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.date.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$binary\\b", - "captures": { - "0": { - "name": "keyword.other.aggBSON.binary.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$unwind\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.unwind.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$sortByCount\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.sortByCount.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$sort\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.sort.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$skip\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.skip.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$setWindowFields\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.setWindowFields.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$searchMeta\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.searchMeta.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$sample\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.sample.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$replaceRoot\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.replaceRoot.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$redact\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.redact.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$project\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.project.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$out\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.out.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$match\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.match.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$lookup\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.lookup.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$limit\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.limit.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$indexStats\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.indexStats.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$group\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.group.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$graphLookup\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.graphLookup.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$geoNear\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.geoNear.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$facet\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.facet.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$documents\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.documents.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$densify\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.densify.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$count\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.count.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$collStats\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.collStats.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$bucketAuto\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.bucketAuto.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$bucket\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.bucket.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$addFields\\b", - "captures": { - "0": { - "name": "keyword.other.aggStageOperators.addFields.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$where\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.where.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$type\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.type.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$text\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.text.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$slice\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.slice.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$size\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.size.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$regex\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.regex.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$or\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.or.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$nor\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.nor.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$not\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.not.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$nin\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.nin.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$nearSphere\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.nearSphere.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$near\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.near.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$ne\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.ne.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$mod\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.mod.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$lte\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.lte.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$lt\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.lt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$jsonSchema\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.jsonSchema.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$in\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.in.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$gte\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.gte.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$gt\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.gt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$geoWithin\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.geoWithin.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$geoIntersects\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.geoIntersects.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$expr\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.expr.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$exists\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.exists.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$eq\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.eq.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$elemMatch\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.elemMatch.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$comment\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.comment.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$bitsAnySet\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.bitsAnySet.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$bitsAnyClear\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.bitsAnyClear.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$bitsAllSet\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.bitsAllSet.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$bitsAllClear\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.bitsAllClear.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$and\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.and.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$all\\b", - "captures": { - "0": { - "name": "keyword.other.QueryOperators.all.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$zip\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.zip.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$year\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.year.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$week\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.week.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$type\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.type.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$trunc\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.trunc.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$tsIncrement\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.tsIncrement.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$tsSecond\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.tsSecond.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toUpper\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.toUpper.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toLower\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.toLower.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$switch\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.switch.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$subtract\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.subtract.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$substrCP\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.substrCP.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$substrBytes\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.substrBytes.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$substr\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.substr.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$strLenCP\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.strLenCP.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$strLenBytes\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.strLenBytes.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$strcasecmp\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.strcasecmp.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$sqrt\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.sqrt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$split\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.split.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$slice\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.slice.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$size\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.size.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$setUnion\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.setUnion.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$setIsSubset\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.setIsSubset.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$setIntersection\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.setIntersection.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$setEquals\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.setEquals.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$setDifference\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.setDifference.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$second\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.second.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$reverseArray\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.reverseArray.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$reduce\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.reduce.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$range\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.range.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$pow\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.pow.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$or\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.or.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$objectToArray\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.objectToArray.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$not\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.not.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$new\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.new.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$multiply\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.multiply.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$month\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.month.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$mod\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.mod.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$minute\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.minute.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$millisecond\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.millisecond.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$meta\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.meta.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$mergeObjects\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.mergeObjects.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$map\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.map.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$log10\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.log10.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$log\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.log.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$ln\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.ln.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$lt\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.lt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$literal\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.literal.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$let\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.let.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$isoWeekYear\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.isoWeekYear.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$isoWeek\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.isoWeek.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$isoDayOfWeek\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.isoDayOfWeek.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$isArray\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.isArray.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$indexOfCP\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.indexOfCP.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$indexOfBytes\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.indexOfBytes.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$indexOfArray\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.indexOfArray.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$in\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.in.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$ifNull\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.ifNull.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$hour\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.hour.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$gte\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.gte.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$gt\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.gt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$getField\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.getField.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$floor\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.floor.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$filter\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.filter.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$exp\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.exp.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$eq\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.eq.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$divide\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.divide.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dayOfYear\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dayOfYear.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dayOfWeek\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dayOfWeek.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dayOfMonth\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dayOfMonth.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateTrunc\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateTrunc.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateToString\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateToString.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateToParts\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateToParts.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateSubtract\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateSubtract.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateFromString\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateFromString.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateFromParts\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateFromParts.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateDiff\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateDiff.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$dateAdd\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.dateAdd.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$cond\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.cond.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$concatArrays\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.concatArrays.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$concat\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.concat.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$cmp\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.cmp.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$ceil\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.ceil.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$arrayToObject\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.arrayToObject.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$arrayElemAt\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.arrayElemAt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$anyElementTrue\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.anyElementTrue.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$and\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.and.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$allElementsTrue\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.allElementsTrue.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$add\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.add.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$abs\\b", - "captures": { - "0": { - "name": "keyword.other.aggExpressionOperators.abs.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$trim\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.trim.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toString\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toString.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toObjectId\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toObjectId.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toLong\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toLong.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toInt\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toInt.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toDouble\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toDouble.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toDecimal\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toDecimal.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toDate\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toDate.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$toBool\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.toBool.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$rtrim\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.rtrim.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$ltrim\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.ltrim.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$convert\\b", - "captures": { - "0": { - "name": "keyword.other.aggConverters.convert.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$sum\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.sum.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$shift\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.shift.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$stdDevSamp\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.stdDevSamp.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$stdDevPop\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.stdDevPop.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$rank\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.rank.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$push\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.push.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$min\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.min.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$max\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.max.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$last\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.last.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$integral\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.integral.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$first\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.first.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$expMovingAvg\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.expMovingAvg.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$documentNumber\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.documentNumber.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$denseRank\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.denseRank.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$derivative\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.derivative.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$count\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.count.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$covarianceSamp\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.covarianceSamp.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$covariancePop\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.covariancePop.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$avg\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.avg.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "\\$addToSet\\b", - "captures": { - "0": { - "name": "keyword.other.aggAccumulators.addToSet.mongodb" - } - } - }, - { - "include": "#comment" - }, - { - "include": "#object-literal-method-declaration" - }, - { - "name": "meta.object.member.mongodb meta.object-literal.key.mongodb", - "begin": "(?=\\[)", - "end": "(?=:)|((?<=[\\]])(?=\\s*[\\(\\<]))", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#array-literal" - } - ] - }, - { - "name": "meta.object.member.mongodb meta.object-literal.key.mongodb", - "begin": "(?=[\\'\\\"\\`])", - "end": "(?=:)|((?<=[\\'\\\"\\`])(?=((\\s*[\\(\\<,}])|(\\s+(as)\\s+))))", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#string" - } - ] - }, - { - "name": "meta.object.member.mongodb meta.object-literal.key.mongodb", - "begin": "(?x)(?=(\\b(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "0": { - "name": "meta.object-literal.key.mongodb" - }, - "1": { - "name": "entity.name.function.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*:)", - "captures": { - "0": { - "name": "meta.object-literal.key.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "begin": "\\.\\.\\.", - "beginCaptures": { - "0": { - "name": "keyword.operator.spread.mongodb" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.mongodb", - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$|\\/\\/|\\/\\*)", - "captures": { - "1": { - "name": "variable.other.readwrite.mongodb" - } - } - }, - { - "name": "meta.object.member.mongodb", - "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - } - }, - "end": "(?<=\\))", - "patterns": [ - { - "include": "#type-parameters" - }, - { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "meta.brace.round.mongodb" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.mongodb" - } - }, - "patterns": [ - { - "include": "#expression-inside-possibly-arrow-parens" - } - ] - } - ] - }, - { - "begin": "(?<=:)\\s*(async)?\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - }, - "2": { - "name": "meta.brace.round.mongodb" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.mongodb" - } - }, - "patterns": [ - { - "include": "#expression-inside-possibly-arrow-parens" - } - ] - }, - { - "begin": "(?<=:)\\s*(async)?\\s*(?=\\<\\s*$)", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - } - }, - "end": "(?<=\\>)", - "patterns": [ - { - "include": "#type-parameters" - } - ] - }, - { - "begin": "(?<=\\>)\\s*(\\()(?=\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", - "beginCaptures": { - "1": { - "name": "meta.brace.round.mongodb" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.mongodb" - } - }, - "patterns": [ - { - "include": "#expression-inside-possibly-arrow-parens" - } - ] - }, - { - "include": "#possibly-arrow-return-type" - }, - { - "include": "#expression" - } - ] - }, - { - "include": "#punctuation-comma" - } - ] - }, - "ternary-expression": { - "begin": "(?!\\?\\.\\s*[^[:digit:]])(\\?)(?!\\?)", - "beginCaptures": { - "1": { - "name": "keyword.operator.ternary.mongodb" - } - }, - "end": "\\s*(:)", - "endCaptures": { - "1": { - "name": "keyword.operator.ternary.mongodb" - } - }, - "patterns": [ - { - "include": "#expression" - } - ] - }, - "function-call": { - "begin": "(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?(<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()", - "end": "(?<=\\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\\)]))\\s*(?:(\\?\\.\\s*)|(\\!))?(<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()", - "patterns": [ - { - "name": "meta.function-call.mongodb", - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*)(\\s*\\??\\.\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(?:(\\?\\.\\s*)|(\\!))?(<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()", - "patterns": [ - { - "include": "#support-function-call-identifiers" - }, - { - "name": "entity.name.function.mongodb", - "match": "(\\#?[_$[:alpha:]][_$[:alnum:]]*)" - } - ] - }, - { - "include": "#comment" - }, - { - "name": "meta.function-call.mongodb punctuation.accessor.optional.mongodb", - "match": "\\?\\." - }, - { - "name": "meta.function-call.mongodb keyword.operator.definiteassignment.mongodb", - "match": "\\!" - }, - { - "include": "#type-arguments" - }, - { - "include": "#paren-expression" - } - ] - }, - "support-function-call-identifiers": { - "patterns": [ - { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "keyword.operator.expression.import.mongodb", - "match": "(?:(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\(\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - } - }, - "end": "(?<=\\))", - "patterns": [ - { - "include": "#paren-expression-possibly-arrow-with-typeparameters" - } - ] - }, - { - "begin": "(?<=[(=,]|=>|^return|[^\\._$[:alnum:]]return)\\s*(async)?(?=\\s*((((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*))?\\()|(<))\\s*$)", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.mongodb" - } - }, - "end": "(?<=\\))", - "patterns": [ - { - "include": "#paren-expression-possibly-arrow-with-typeparameters" - } - ] - }, - { - "include": "#possibly-arrow-return-type" - } - ] - }, - "paren-expression-possibly-arrow-with-typeparameters": { - "patterns": [ - { - "include": "#type-parameters" - }, - { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "meta.brace.round.mongodb" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.mongodb" - } - }, - "patterns": [ - { - "include": "#expression-inside-possibly-arrow-parens" - } - ] - } - ] - }, - "expression-inside-possibly-arrow-parens": { - "patterns": [ - { - "include": "#expressionWithoutIdentifiers" - }, - { - "include": "#comment" - }, - { - "include": "#string" - }, - { - "include": "#decorator" - }, - { - "include": "#destructuring-parameter" - }, - { - "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "1": { - "name": "storage.modifier.mongodb" - }, - "2": { - "name": "keyword.operator.rest.mongodb" - }, - "3": { - "name": "entity.name.function.mongodb variable.language.this.mongodb" - }, - "4": { - "name": "entity.name.function.mongodb" - }, - "5": { - "name": "keyword.operator.optional.mongodb" - } - } - }, - { - "match": "(?x)(?:(?)", - "captures": { - "1": { - "name": "meta.brace.angle.mongodb" - }, - "2": { - "name": "storage.modifier.mongodb" - }, - "3": { - "name": "meta.brace.angle.mongodb" - } - } - }, - { - "name": "cast.expr.mongodb", - "begin": "(?:(?*?\\&\\|\\^]|[^_$[:alnum:]](?:\\+\\+|\\-\\-)|[^\\+]\\+|[^\\-]\\-))\\s*(<)(?!)", - "endCaptures": { - "1": { - "name": "meta.brace.angle.mongodb" - } - }, - "patterns": [ - { - "include": "#type" - } - ] - }, - { - "name": "cast.expr.mongodb", - "begin": "(?:(?<=^))\\s*(<)(?=[_$[:alpha:]][_$[:alnum:]]*\\s*>)", - "beginCaptures": { - "1": { - "name": "meta.brace.angle.mongodb" - } - }, - "end": "(\\>)", - "endCaptures": { - "1": { - "name": "meta.brace.angle.mongodb" - } - }, - "patterns": [ - { - "include": "#type" - } - ] - } - ] - }, - "expression-operators": { - "patterns": [ - { - "name": "keyword.control.flow.mongodb", - "match": "(?>=|>>>=|\\|=" - }, - { - "name": "keyword.operator.bitwise.shift.mongodb", - "match": "<<|>>>|>>" - }, - { - "name": "keyword.operator.comparison.mongodb", - "match": "===|!==|==|!=" - }, - { - "name": "keyword.operator.relational.mongodb", - "match": "<=|>=|<>|<|>" - }, - { - "match": "(\\!)\\s*(/)(?![/*])", - "captures": { - "1": { - "name": "keyword.operator.logical.mongodb" - }, - "2": { - "name": "keyword.operator.arithmetic.mongodb" - } - } - }, - { - "name": "keyword.operator.logical.mongodb", - "match": "\\!|&&|\\|\\||\\?\\?" - }, - { - "name": "keyword.operator.bitwise.mongodb", - "match": "\\&|~|\\^|\\|" - }, - { - "name": "keyword.operator.assignment.mongodb", - "match": "\\=" - }, - { - "name": "keyword.operator.decrement.mongodb", - "match": "--" - }, - { - "name": "keyword.operator.increment.mongodb", - "match": "\\+\\+" - }, - { - "name": "keyword.operator.arithmetic.mongodb", - "match": "%|\\*|/|-|\\+" - }, - { - "begin": "(?<=[_$[:alnum:])\\]])\\s*(?=(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)+(/)(?![/*]))", - "end": "(/)(?!\\*([^\\*]|(\\*[^\\/]))*\\*\\/)", - "endCaptures": { - "1": { - "name": "keyword.operator.arithmetic.mongodb" - } - }, - "patterns": [ - { - "include": "#comment" - } - ] - }, - { - "match": "(?<=[_$[:alnum:])\\]])\\s*(/)(?![/*])", - "captures": { - "1": { - "name": "keyword.operator.arithmetic.mongodb" - } - } - } - ] - }, - "typeof-operator": { - "name": "keyword.operator.expression.typeof.mongodb", - "match": "(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\())\n |\n (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\\b(?!\\$)))", - "captures": { - "1": { - "name": "punctuation.accessor.mongodb" - }, - "2": { - "name": "punctuation.accessor.optional.mongodb" - }, - "3": { - "name": "support.variable.property.mongodb" - }, - "4": { - "name": "support.constant.mongodb" - } - } - }, - { - "match": "(?x) (?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\\()", - "captures": { - "1": { - "name": "punctuation.accessor.mongodb" - }, - "2": { - "name": "punctuation.accessor.optional.mongodb" - }, - "3": { - "name": "support.constant.dom.mongodb" - }, - "4": { - "name": "support.variable.property.dom.mongodb" - } - } - }, - { - "name": "support.class.node.mongodb", - "match": "(?x)(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))))) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n ))\n))", - "captures": { - "1": { - "name": "punctuation.accessor.mongodb" - }, - "2": { - "name": "punctuation.accessor.optional.mongodb" - }, - "3": { - "name": "entity.name.function.mongodb" - } - } - }, - { - "match": "(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*(\\#?[[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "captures": { - "1": { - "name": "punctuation.accessor.mongodb" - }, - "2": { - "name": "punctuation.accessor.optional.mongodb" - }, - "3": { - "name": "variable.other.constant.property.mongodb" - } - } - }, - { - "match": "(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*(\\#?[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.mongodb" - }, - "2": { - "name": "punctuation.accessor.optional.mongodb" - }, - "3": { - "name": "variable.other.property.mongodb" - } - } - }, - { - "name": "variable.other.constant.mongodb", - "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" - }, - { - "name": "variable.other.readwrite.mongodb", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "object-identifiers": { - "patterns": [ - { - "name": "support.class.mongodb", - "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\??\\.\\s*prototype\\b(?!\\$))" - }, - { - "match": "(?x)(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))\\s*(?:\n (\\#?[[:upper:]][_$[:digit:][:upper:]]*) |\n (\\#?[_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.mongodb" - }, - "2": { - "name": "punctuation.accessor.optional.mongodb" - }, - "3": { - "name": "variable.other.constant.object.property.mongodb" - }, - "4": { - "name": "variable.other.object.property.mongodb" - } - } - }, - { - "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\??\\.\\s*\\#?[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "variable.other.constant.object.mongodb" - }, - "2": { - "name": "variable.other.object.mongodb" - } - } - } - ] - }, - "type-annotation": { - "patterns": [ - { - "name": "meta.type.annotation.mongodb", - "begin": "(:)(?=\\s*\\S)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.mongodb" - } - }, - "end": "(?])|((?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)))", - "patterns": [ - { - "include": "#type" - } - ] - }, - { - "name": "meta.type.annotation.mongodb", - "begin": "(:)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.mongodb" - } - }, - "end": "(?])|(?=^\\s*$)|((?<=\\S)(?=\\s*$))|((?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)))", - "patterns": [ - { - "include": "#type" - } - ] - } - ] - }, - "parameter-type-annotation": { - "patterns": [ - { - "name": "meta.type.annotation.mongodb", - "begin": "(:)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.mongodb" - } - }, - "end": "(?=[,)])|(?==[^>])", - "patterns": [ - { - "include": "#type" - } - ] - } - ] - }, - "return-type": { - "patterns": [ - { - "name": "meta.return.type.mongodb", - "begin": "(?<=\\))\\s*(:)(?=\\s*\\S)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.mongodb" - } - }, - "end": "(?|\\{|(^\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\s+))", - "patterns": [ - { - "include": "#arrow-return-type-body" - } - ] - }, - "possibly-arrow-return-type": { - "begin": "(?<=\\)|^)\\s*(:)(?=\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*=>)", - "beginCaptures": { - "1": { - "name": "meta.arrow.mongodb meta.return.type.arrow.mongodb keyword.operator.type.annotation.mongodb" - } - }, - "end": "(?==>|\\{|(^\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\s+))", - "contentName": "meta.arrow.mongodb meta.return.type.arrow.mongodb", - "patterns": [ - { - "include": "#arrow-return-type-body" - } - ] - }, - "arrow-return-type-body": { - "patterns": [ - { - "begin": "(?<=[:])(?=\\s*\\{)", - "end": "(?<=\\})", - "patterns": [ - { - "include": "#type-object" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "type-parameters": { - "name": "meta.type.parameters.mongodb", - "begin": "(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.mongodb" - } - }, - "end": "(>)", - "endCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.end.mongodb" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "name": "storage.modifier.mongodb", - "match": "(?)" - } - ] - }, - "type-arguments": { - "name": "meta.type.parameters.mongodb", - "begin": "\\<", - "beginCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.begin.mongodb" - } - }, - "end": "\\>", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.mongodb" - } - }, - "patterns": [ - { - "include": "#type-arguments-body" - } - ] - }, - "type-arguments-body": { - "patterns": [ - { - "match": "(?)\n ))\n ))\n)) |\n(:\\s*(?]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?[\\(]\\s*((([\\{\\[]\\s*)?$)|((\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})\\s*((:\\s*\\{?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*)))|((\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])\\s*((:\\s*\\[?$)|((\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<[^<>]+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+\\s*)?=\\s*))))))))", - "captures": { - "1": { - "name": "storage.modifier.mongodb" - }, - "2": { - "name": "keyword.operator.rest.mongodb" - }, - "3": { - "name": "entity.name.function.mongodb variable.language.this.mongodb" - }, - "4": { - "name": "entity.name.function.mongodb" - }, - "5": { - "name": "keyword.operator.optional.mongodb" - } - } - }, - { - "match": "(?x)(?:(?)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type-parameters" - } - ] - }, - { - "name": "meta.type.constructor.mongodb", - "begin": "(?)\n ))\n )\n )\n)", - "end": "(?<=\\))", - "patterns": [ - { - "include": "#function-parameters" - } - ] - } - ] - }, - "type-function-return-type": { - "patterns": [ - { - "name": "meta.type.function.return.mongodb", - "begin": "(=>)(?=\\s*\\S)", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.mongodb" - } - }, - "end": "(?)(?:\\?]|//|$)", - "patterns": [ - { - "include": "#type-function-return-type-core" - } - ] - }, - { - "name": "meta.type.function.return.mongodb", - "begin": "=>", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.mongodb" - } - }, - "end": "(?)(?]|//|^\\s*$)|((?<=\\S)(?=\\s*$)))", - "patterns": [ - { - "include": "#type-function-return-type-core" - } - ] - } - ] - }, - "type-function-return-type-core": { - "patterns": [ - { - "include": "#comment" - }, - { - "begin": "(?<==>)(?=\\s*\\{)", - "end": "(?<=\\})", - "patterns": [ - { - "include": "#type-object" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "type-operators": { - "patterns": [ - { - "include": "#typeof-operator" - }, - { - "begin": "([&|])(?=\\s*\\{)", - "beginCaptures": { - "0": { - "name": "keyword.operator.type.mongodb" - } - }, - "end": "(?<=\\})", - "patterns": [ - { - "include": "#type-object" - } - ] - }, - { - "begin": "[&|]", - "beginCaptures": { - "0": { - "name": "keyword.operator.type.mongodb" - } - }, - "end": "(?=\\S)" - }, - { - "name": "keyword.operator.expression.keyof.mongodb", - "match": "(?)", - "endCaptures": { - "1": { - "name": "meta.type.parameters.mongodb punctuation.definition.typeparameters.end.mongodb" - } - }, - "contentName": "meta.type.parameters.mongodb", - "patterns": [ - { - "include": "#type-arguments-body" - } - ] - }, - { - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(<)", - "beginCaptures": { - "1": { - "name": "entity.name.type.mongodb" - }, - "2": { - "name": "meta.type.parameters.mongodb punctuation.definition.typeparameters.begin.mongodb" - } - }, - "end": "(>)", - "endCaptures": { - "1": { - "name": "meta.type.parameters.mongodb punctuation.definition.typeparameters.end.mongodb" - } - }, - "contentName": "meta.type.parameters.mongodb", - "patterns": [ - { - "include": "#type-arguments-body" - } - ] - }, - { - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))", - "captures": { - "1": { - "name": "entity.name.type.module.mongodb" - }, - "2": { - "name": "punctuation.accessor.mongodb" - }, - "3": { - "name": "punctuation.accessor.optional.mongodb" - } - } - }, - { - "name": "entity.name.type.mongodb", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "punctuation-comma": { - "name": "punctuation.separator.comma.mongodb", - "match": "," - }, - "punctuation-semicolon": { - "name": "punctuation.terminator.statement.mongodb", - "match": ";" - }, - "punctuation-accessor": { - "match": "(?:(\\.)|(\\?\\.(?!\\s*[[:digit:]])))", - "captures": { - "1": { - "name": "punctuation.accessor.mongodb" - }, - "2": { - "name": "punctuation.accessor.optional.mongodb" - } - } - }, - "string": { - "patterns": [ - { - "include": "#qstring-single" - }, - { - "include": "#qstring-double" - }, - { - "include": "#template" - } - ] - }, - "qstring-double": { - "name": "string.quoted.double.mongodb", - "begin": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.mongodb" - } - }, - "end": "(\")|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.mongodb" - }, - "2": { - "name": "invalid.illegal.newline.mongodb" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "qstring-single": { - "name": "string.quoted.single.mongodb", - "begin": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.mongodb" - } - }, - "end": "(\\')|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.mongodb" - }, - "2": { - "name": "invalid.illegal.newline.mongodb" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "string-character-escape": { - "name": "constant.character.escape.mongodb", - "match": "\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|u\\{[0-9A-Fa-f]+\\}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)" - }, - "template": { - "patterns": [ - { - "name": "string.template.mongodb", - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "end": "(?=`)", - "patterns": [ - { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=(<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?`)", - "patterns": [ - { - "include": "#support-function-call-identifiers" - }, - { - "name": "entity.name.function.tagged-template.mongodb", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - } - ] - }, - { - "include": "#type-arguments" - } - ] - }, - { - "name": "string.template.mongodb", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof|readonly)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)", - "beginCaptures": { - "1": { - "name": "entity.name.function.tagged-template.mongodb" - } - }, - "end": "(?=`)", - "patterns": [ - { - "include": "#type-arguments" - } - ] - }, - { - "name": "string.template.mongodb", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)?(`)", - "beginCaptures": { - "1": { - "name": "entity.name.function.tagged-template.mongodb" - }, - "2": { - "name": "punctuation.definition.string.template.begin.mongodb" - } - }, - "end": "`", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.template.end.mongodb" - } - }, - "patterns": [ - { - "include": "#template-substitution-element" - }, - { - "include": "#string-character-escape" - } - ] - } - ] - }, - "template-substitution-element": { - "name": "meta.template.expression.mongodb", - "begin": "\\$\\{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.template-expression.begin.mongodb" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.template-expression.end.mongodb" - } - }, - "patterns": [ - { - "include": "#expression" - } - ], - "contentName": "meta.embedded.line.mongodb" - }, - "regex": { - "patterns": [ - { - "name": "string.regexp.mongodb", - "begin": "(?|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.mongodb" - } - }, - "end": "(/)([gimsuy]*)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.mongodb" - }, - "2": { - "name": "keyword.other.mongodb" - } - }, - "patterns": [ - { - "include": "#regexp" - } - ] - }, - { - "name": "string.regexp.mongodb", - "begin": "((?", - "captures": { - "0": { - "name": "keyword.other.back-reference.regexp" - }, - "1": { - "name": "variable.other.regexp" - } - } - }, - { - "name": "keyword.operator.quantifier.regexp", - "match": "[?+*]|\\{(\\d+,\\d+|\\d+,|,\\d+|\\d+)\\}\\??" - }, - { - "name": "keyword.operator.or.regexp", - "match": "\\|" - }, - { - "name": "meta.group.assertion.regexp", - "begin": "(\\()((\\?=)|(\\?!)|(\\?<=)|(\\?))?", - "beginCaptures": { - "0": { - "name": "punctuation.definition.group.regexp" - }, - "1": { - "name": "punctuation.definition.group.no-capture.regexp" - }, - "2": { - "name": "variable.other.regexp" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.group.regexp" - } - }, - "patterns": [ - { - "include": "#regexp" - } - ] - }, - { - "name": "constant.other.character-class.set.regexp", - "begin": "(\\[)(\\^)?", - "beginCaptures": { - "1": { - "name": "punctuation.definition.character-class.regexp" - }, - "2": { - "name": "keyword.operator.negation.regexp" - } - }, - "end": "(\\])", - "endCaptures": { - "1": { - "name": "punctuation.definition.character-class.regexp" - } - }, - "patterns": [ - { - "name": "constant.other.character-class.range.regexp", - "match": "(?:.|(\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\c[A-Z])|(\\\\.))\\-(?:[^\\]\\\\]|(\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\c[A-Z])|(\\\\.))", - "captures": { - "1": { - "name": "constant.character.numeric.regexp" - }, - "2": { - "name": "constant.character.control.regexp" - }, - "3": { - "name": "constant.character.escape.backslash.regexp" - }, - "4": { - "name": "constant.character.numeric.regexp" - }, - "5": { - "name": "constant.character.control.regexp" - }, - "6": { - "name": "constant.character.escape.backslash.regexp" - } - } - }, - { - "include": "#regex-character-class" - } - ] - }, - { - "include": "#regex-character-class" - } - ] - }, - "regex-character-class": { - "patterns": [ - { - "name": "constant.other.character-class.regexp", - "match": "\\\\[wWsSdDtrnvf]|\\." - }, - { - "name": "constant.character.numeric.regexp", - "match": "\\\\([0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})" - }, - { - "name": "constant.character.control.regexp", - "match": "\\\\c[A-Z]" - }, - { - "name": "constant.character.escape.backslash.regexp", - "match": "\\\\." - } - ] - }, - "comment": { - "patterns": [ - { - "name": "comment.block.documentation.mongodb", - "begin": "/\\*\\*(?!/)", - "beginCaptures": { - "0": { - "name": "punctuation.definition.comment.mongodb" - } - }, - "end": "\\*/", - "endCaptures": { - "0": { - "name": "punctuation.definition.comment.mongodb" - } - }, - "patterns": [ - { - "include": "#docblock" - } - ] - }, - { - "name": "comment.block.mongodb", - "begin": "(/\\*)(?:\\s*((@)internal)(?=\\s|(\\*/)))?", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.mongodb" - }, - "2": { - "name": "storage.type.internaldeclaration.mongodb" - }, - "3": { - "name": "punctuation.decorator.internaldeclaration.mongodb" - } - }, - "end": "\\*/", - "endCaptures": { - "0": { - "name": "punctuation.definition.comment.mongodb" - } - } - }, - { - "begin": "(^[ \\t]+)?((//)(?:\\s*((@)internal)(?=\\s|$))?)", - "beginCaptures": { - "1": { - "name": "punctuation.whitespace.comment.leading.mongodb" - }, - "2": { - "name": "comment.line.double-slash.mongodb" - }, - "3": { - "name": "punctuation.definition.comment.mongodb" - }, - "4": { - "name": "storage.type.internaldeclaration.mongodb" - }, - "5": { - "name": "punctuation.decorator.internaldeclaration.mongodb" - } - }, - "end": "(?=$)", - "contentName": "comment.line.double-slash.mongodb" - } - ] - }, - "single-line-comment-consuming-line-ending": { - "begin": "(^[ \\t]+)?((//)(?:\\s*((@)internal)(?=\\s|$))?)", - "beginCaptures": { - "1": { - "name": "punctuation.whitespace.comment.leading.mongodb" - }, - "2": { - "name": "comment.line.double-slash.mongodb" - }, - "3": { - "name": "punctuation.definition.comment.mongodb" - }, - "4": { - "name": "storage.type.internaldeclaration.mongodb" - }, - "5": { - "name": "punctuation.decorator.internaldeclaration.mongodb" - } - }, - "end": "(?=^)", - "contentName": "comment.line.double-slash.mongodb" - }, - "directives": { - "name": "comment.line.triple-slash.directive.mongodb", - "begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\.)*\\')|(\\\"([^\\\"\\\\]|\\\\.)*\\\")|(\\`([^\\`\\\\]|\\\\.)*\\`)))+\\s*/>\\s*$)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.mongodb" - } - }, - "end": "(?=$)", - "patterns": [ - { - "name": "meta.tag.mongodb", - "begin": "(<)(reference|amd-dependency|amd-module)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.directive.mongodb" - }, - "2": { - "name": "entity.name.tag.directive.mongodb" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.directive.mongodb" - } - }, - "patterns": [ - { - "name": "entity.other.attribute-name.directive.mongodb", - "match": "path|types|no-default-lib|lib|name" - }, - { - "name": "keyword.operator.assignment.mongodb", - "match": "=" - }, - { - "include": "#string" - } - ] - } - ] - }, - "docblock": { - "patterns": [ - { - "match": "(?x)\n((@)(?:access|api))\n\\s+\n(private|protected|public)\n\\b", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "constant.language.access-type.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)author)\n\\s+\n(\n [^@\\s<>*/]\n (?:[^@<>*/]|\\*[^/])*\n)\n(?:\n \\s*\n (<)\n ([^>\\s]+)\n (>)\n)?", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "5": { - "name": "constant.other.email.link.underline.jsdoc" - }, - "6": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)borrows) \\s+\n((?:[^@\\s*/]|\\*[^/])+) # \n\\s+ (as) \\s+ # as\n((?:[^@\\s*/]|\\*[^/])+) # ", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "keyword.operator.control.jsdoc" - }, - "5": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "name": "meta.example.jsdoc", - "begin": "((@)example)\\s+", - "end": "(?=@|\\*/)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "patterns": [ - { - "match": "^\\s\\*\\s+" - }, - { - "contentName": "constant.other.description.jsdoc", - "begin": "\\G(<)caption(>)", - "beginCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - }, - "end": "()|(?=\\*/)", - "endCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - } - }, - { - "match": "[^\\s@*](?:[^*]|\\*[^/])*", - "captures": { - "0": { - "name": "source.embedded.mongodb" - } - } - } - ] - }, - { - "match": "(?x) ((@)kind) \\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\b", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "constant.language.symbol-type.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)see)\n\\s+\n(?:\n # URL\n (\n (?=https?://)\n (?:[^\\s*]|\\*[^/])+\n )\n |\n # JSDoc namepath\n (\n (?!\n # Avoid matching bare URIs (also acceptable as links)\n https?://\n |\n # Avoid matching {@inline tags}; we match those below\n (?:\\[[^\\[\\]]*\\])? # Possible description [preceding]{@tag}\n {@(?:link|linkcode|linkplain|tutorial)\\b\n )\n # Matched namepath\n (?:[^@\\s*/]|\\*[^/])+\n )\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.link.underline.jsdoc" - }, - "4": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)template)\n\\s+\n# One or more valid identifiers\n(\n [A-Za-z_$] # First character: non-numeric word character\n [\\w$.\\[\\]]* # Rest of identifier\n (?: # Possible list of additional identifiers\n \\s* , \\s*\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n )*\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "match": "(?x)\n(\n (@)\n (?:arg|argument|const|constant|member|namespace|param|var)\n)\n\\s+\n(\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "begin": "((@)typedef)\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "entity.name.type.instance.jsdoc", - "match": "(?:[^@\\s*/]|\\*[^/])+" - } - ] - }, - { - "begin": "((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "variable.other.jsdoc", - "match": "([A-Za-z_$][\\w$.\\[\\]]*)" - }, - { - "name": "variable.other.jsdoc", - "match": "(?x)\n(\\[)\\s*\n[\\w$]+\n(?:\n (?:\\[\\])? # Foo[ ].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [\\w$]+\n)*\n(?:\n \\s*\n (=) # [foo=bar] Default parameter value\n \\s*\n (\n # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\n (?>\n \"(?:(?:\\*(?!/))|(?:\\\\(?!\"))|[^*\\\\])*?\" | # [foo=\"bar\"] Double-quoted\n '(?:(?:\\*(?!/))|(?:\\\\(?!'))|[^*\\\\])*?' | # [foo='bar'] Single-quoted\n \\[ (?:(?:\\*(?!/))|[^*])*? \\] | # [foo=[1,2]] Array literal\n (?:(?:\\*(?!/))|\\s(?!\\s*\\])|\\[.*?(?:\\]|(?=\\*/))|[^*\\s\\[\\]])* # Everything else\n )*\n )\n)?\n\\s*(?:(\\])((?:[^*\\s]|\\*[^\\s/])+)?|(?=\\*/))", - "captures": { - "1": { - "name": "punctuation.definition.optional-value.begin.bracket.square.jsdoc" - }, - "2": { - "name": "keyword.operator.assignment.jsdoc" - }, - "3": { - "name": "source.embedded.mongodb" - }, - "4": { - "name": "punctuation.definition.optional-value.end.bracket.square.jsdoc" - }, - "5": { - "name": "invalid.illegal.syntax.jsdoc" - } - } - } - ] - }, - { - "begin": "(?x)\n(\n (@)\n (?:define|enum|exception|export|extends|lends|implements|modifies\n |namespace|private|protected|returns?|suppress|this|throws|type\n |yields?)\n)\n\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - } - ] - }, - { - "match": "(?x)\n(\n (@)\n (?:alias|augments|callback|constructs|emits|event|fires|exports?\n |extends|external|function|func|host|lends|listens|interface|memberof!?\n |method|module|mixes|mixin|name|requires|see|this|typedef|uses)\n)\n\\s+\n(\n (?:\n [^{}@\\s*] | \\*[^/]\n )+\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "contentName": "variable.other.jsdoc", - "begin": "((@)(?:default(?:value)?|license|version))\\s+(([''\"]))", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - }, - "4": { - "name": "punctuation.definition.string.begin.jsdoc" - } - }, - "end": "(\\3)|(?=$|\\*/)", - "endCaptures": { - "0": { - "name": "variable.other.jsdoc" - }, - "1": { - "name": "punctuation.definition.string.end.jsdoc" - } - } - }, - { - "match": "((@)(?:default(?:value)?|license|tutorial|variation|version))\\s+([^\\s*]+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "name": "storage.type.class.jsdoc", - "match": "(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\b", - "captures": { - "1": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - }, - { - "include": "#inline-tags" - }, - { - "match": "((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\\s+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - } - ] - }, - "brackets": { - "patterns": [ - { - "begin": "{", - "end": "}|(?=\\*/)", - "patterns": [ - { - "include": "#brackets" - } - ] - }, - { - "begin": "\\[", - "end": "\\]|(?=\\*/)", - "patterns": [ - { - "include": "#brackets" - } - ] - } - ] - }, - "inline-tags": { - "patterns": [ - { - "name": "constant.other.description.jsdoc", - "match": "(\\[)[^\\]]+(\\])(?={@(?:link|linkcode|linkplain|tutorial))", - "captures": { - "1": { - "name": "punctuation.definition.bracket.square.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.square.end.jsdoc" - } - } - }, - { - "name": "entity.name.type.instance.jsdoc", - "begin": "({)((@)(?:link(?:code|plain)?|tutorial))\\s*", - "beginCaptures": { - "1": { - "name": "punctuation.definition.bracket.curly.begin.jsdoc" - }, - "2": { - "name": "storage.type.class.jsdoc" - }, - "3": { - "name": "punctuation.definition.inline.tag.jsdoc" - } - }, - "end": "}|(?=\\*/)", - "endCaptures": { - "0": { - "name": "punctuation.definition.bracket.curly.end.jsdoc" - } - }, - "patterns": [ - { - "match": "\\G((?=https?://)(?:[^|}\\s*]|\\*[/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.link.underline.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - }, - { - "match": "\\G((?:[^{}@\\s|*]|\\*[^/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.description.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - } - ] - } - ] - }, - "jsdoctype": { - "patterns": [ - { - "name": "invalid.illegal.type.jsdoc", - "match": "\\G{(?:[^}*]|\\*[^/}])+$" - }, - { - "contentName": "entity.name.type.instance.jsdoc", - "begin": "\\G({)", - "beginCaptures": { - "0": { - "name": "entity.name.type.instance.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.curly.begin.jsdoc" - } - }, - "end": "((}))\\s*|(?=\\*/)", - "endCaptures": { - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.curly.end.jsdoc" - } - }, - "patterns": [ - { - "include": "#brackets" - } - ] - } - ] - } - } -} \ No newline at end of file diff --git a/syntaxes/mongodbInjection.tmLanguage.json b/syntaxes/mongodbInjection.tmLanguage.json new file mode 100644 index 000000000..a6fc81f2b --- /dev/null +++ b/syntaxes/mongodbInjection.tmLanguage.json @@ -0,0 +1,2022 @@ +{ + "scopeName": "mongodb.injection", + "injectionSelector": "L:meta.objectliteral.js", + "patterns": [ + { + "include": "#object-member" + } + ], + "repository": { + "object-member": { + "patterns": [ + { + "name": "meta.object.member.mongodb", + "match": "\\$accumulator\\b", + "captures": { + "0": { + "name": "keyword.other.$accumulator.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$addToSet\\b", + "captures": { + "0": { + "name": "keyword.other.$addToSet.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$avg\\b", + "captures": { + "0": { + "name": "keyword.other.$avg.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bottom\\b", + "captures": { + "0": { + "name": "keyword.other.$bottom.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bottomN\\b", + "captures": { + "0": { + "name": "keyword.other.$bottomN.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$covariancePop\\b", + "captures": { + "0": { + "name": "keyword.other.$covariancePop.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$covarianceSamp\\b", + "captures": { + "0": { + "name": "keyword.other.$covarianceSamp.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$count\\b", + "captures": { + "0": { + "name": "keyword.other.$count.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$derivative\\b", + "captures": { + "0": { + "name": "keyword.other.$derivative.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$denseRank\\b", + "captures": { + "0": { + "name": "keyword.other.$denseRank.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$documentNumber\\b", + "captures": { + "0": { + "name": "keyword.other.$documentNumber.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$expMovingAvg\\b", + "captures": { + "0": { + "name": "keyword.other.$expMovingAvg.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$first\\b", + "captures": { + "0": { + "name": "keyword.other.$first.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$firstN\\b", + "captures": { + "0": { + "name": "keyword.other.$firstN.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$integral\\b", + "captures": { + "0": { + "name": "keyword.other.$integral.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$last\\b", + "captures": { + "0": { + "name": "keyword.other.$last.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$lastN\\b", + "captures": { + "0": { + "name": "keyword.other.$lastN.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$max\\b", + "captures": { + "0": { + "name": "keyword.other.$max.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$maxN\\b", + "captures": { + "0": { + "name": "keyword.other.$maxN.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$min\\b", + "captures": { + "0": { + "name": "keyword.other.$min.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$minN\\b", + "captures": { + "0": { + "name": "keyword.other.$minN.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$push\\b", + "captures": { + "0": { + "name": "keyword.other.$push.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$rank\\b", + "captures": { + "0": { + "name": "keyword.other.$rank.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$stdDevPop\\b", + "captures": { + "0": { + "name": "keyword.other.$stdDevPop.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$stdDevSamp\\b", + "captures": { + "0": { + "name": "keyword.other.$stdDevSamp.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$shift\\b", + "captures": { + "0": { + "name": "keyword.other.$shift.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$sum\\b", + "captures": { + "0": { + "name": "keyword.other.$sum.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$top\\b", + "captures": { + "0": { + "name": "keyword.other.$top.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$topN\\b", + "captures": { + "0": { + "name": "keyword.other.$topN.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$locf\\b", + "captures": { + "0": { + "name": "keyword.other.$locf.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$linearFill\\b", + "captures": { + "0": { + "name": "keyword.other.$linearFill.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$convert\\b", + "captures": { + "0": { + "name": "keyword.other.$convert.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$ltrim\\b", + "captures": { + "0": { + "name": "keyword.other.$ltrim.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$rtrim\\b", + "captures": { + "0": { + "name": "keyword.other.$rtrim.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toBool\\b", + "captures": { + "0": { + "name": "keyword.other.$toBool.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toDate\\b", + "captures": { + "0": { + "name": "keyword.other.$toDate.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toDecimal\\b", + "captures": { + "0": { + "name": "keyword.other.$toDecimal.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toDouble\\b", + "captures": { + "0": { + "name": "keyword.other.$toDouble.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toInt\\b", + "captures": { + "0": { + "name": "keyword.other.$toInt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toLong\\b", + "captures": { + "0": { + "name": "keyword.other.$toLong.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toObjectId\\b", + "captures": { + "0": { + "name": "keyword.other.$toObjectId.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toString\\b", + "captures": { + "0": { + "name": "keyword.other.$toString.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$trim\\b", + "captures": { + "0": { + "name": "keyword.other.$trim.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$abs\\b", + "captures": { + "0": { + "name": "keyword.other.$abs.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$accumulator\\b", + "captures": { + "0": { + "name": "keyword.other.$accumulator.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$add\\b", + "captures": { + "0": { + "name": "keyword.other.$add.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$allElementsTrue\\b", + "captures": { + "0": { + "name": "keyword.other.$allElementsTrue.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$and\\b", + "captures": { + "0": { + "name": "keyword.other.$and.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$anyElementTrue\\b", + "captures": { + "0": { + "name": "keyword.other.$anyElementTrue.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$arrayElemAt\\b", + "captures": { + "0": { + "name": "keyword.other.$arrayElemAt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$arrayToObject\\b", + "captures": { + "0": { + "name": "keyword.other.$arrayToObject.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$binarySize\\b", + "captures": { + "0": { + "name": "keyword.other.$binarySize.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bsonSize\\b", + "captures": { + "0": { + "name": "keyword.other.$bsonSize.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$ceil\\b", + "captures": { + "0": { + "name": "keyword.other.$ceil.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$cmp\\b", + "captures": { + "0": { + "name": "keyword.other.$cmp.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$concat\\b", + "captures": { + "0": { + "name": "keyword.other.$concat.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$concatArrays\\b", + "captures": { + "0": { + "name": "keyword.other.$concatArrays.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$cond\\b", + "captures": { + "0": { + "name": "keyword.other.$cond.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateAdd\\b", + "captures": { + "0": { + "name": "keyword.other.$dateAdd.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateDiff\\b", + "captures": { + "0": { + "name": "keyword.other.$dateDiff.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateFromParts\\b", + "captures": { + "0": { + "name": "keyword.other.$dateFromParts.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateFromString\\b", + "captures": { + "0": { + "name": "keyword.other.$dateFromString.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateSubtract\\b", + "captures": { + "0": { + "name": "keyword.other.$dateSubtract.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateToParts\\b", + "captures": { + "0": { + "name": "keyword.other.$dateToParts.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateToString\\b", + "captures": { + "0": { + "name": "keyword.other.$dateToString.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateTrunc\\b", + "captures": { + "0": { + "name": "keyword.other.$dateTrunc.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dayOfMonth\\b", + "captures": { + "0": { + "name": "keyword.other.$dayOfMonth.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dayOfWeek\\b", + "captures": { + "0": { + "name": "keyword.other.$dayOfWeek.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dayOfYear\\b", + "captures": { + "0": { + "name": "keyword.other.$dayOfYear.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$dateToString\\b", + "captures": { + "0": { + "name": "keyword.other.$dateToString.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$divide\\b", + "captures": { + "0": { + "name": "keyword.other.$divide.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$eq\\b", + "captures": { + "0": { + "name": "keyword.other.$eq.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$exp\\b", + "captures": { + "0": { + "name": "keyword.other.$exp.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$filter\\b", + "captures": { + "0": { + "name": "keyword.other.$filter.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$first\\b", + "captures": { + "0": { + "name": "keyword.other.$first.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$floor\\b", + "captures": { + "0": { + "name": "keyword.other.$floor.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$function\\b", + "captures": { + "0": { + "name": "keyword.other.$function.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$getField\\b", + "captures": { + "0": { + "name": "keyword.other.$getField.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$gt\\b", + "captures": { + "0": { + "name": "keyword.other.$gt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$gte\\b", + "captures": { + "0": { + "name": "keyword.other.$gte.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$hour\\b", + "captures": { + "0": { + "name": "keyword.other.$hour.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$ifNull\\b", + "captures": { + "0": { + "name": "keyword.other.$ifNull.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$in\\b", + "captures": { + "0": { + "name": "keyword.other.$in.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$indexOfArray\\b", + "captures": { + "0": { + "name": "keyword.other.$indexOfArray.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$indexOfBytes\\b", + "captures": { + "0": { + "name": "keyword.other.$indexOfBytes.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$indexOfCP\\b", + "captures": { + "0": { + "name": "keyword.other.$indexOfCP.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$isArray\\b", + "captures": { + "0": { + "name": "keyword.other.$isArray.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$isNumber\\b", + "captures": { + "0": { + "name": "keyword.other.$isNumber.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$isoDayOfWeek\\b", + "captures": { + "0": { + "name": "keyword.other.$isoDayOfWeek.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$isoWeek\\b", + "captures": { + "0": { + "name": "keyword.other.$isoWeek.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$isoWeekYear\\b", + "captures": { + "0": { + "name": "keyword.other.$isoWeekYear.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$last\\b", + "captures": { + "0": { + "name": "keyword.other.$last.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$let\\b", + "captures": { + "0": { + "name": "keyword.other.$let.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$literal\\b", + "captures": { + "0": { + "name": "keyword.other.$literal.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$lt\\b", + "captures": { + "0": { + "name": "keyword.other.$lt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$lt\\b", + "captures": { + "0": { + "name": "keyword.other.$lt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$ln\\b", + "captures": { + "0": { + "name": "keyword.other.$ln.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$log\\b", + "captures": { + "0": { + "name": "keyword.other.$log.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$log10\\b", + "captures": { + "0": { + "name": "keyword.other.$log10.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$map\\b", + "captures": { + "0": { + "name": "keyword.other.$map.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$mergeObjects\\b", + "captures": { + "0": { + "name": "keyword.other.$mergeObjects.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$meta\\b", + "captures": { + "0": { + "name": "keyword.other.$meta.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$millisecond\\b", + "captures": { + "0": { + "name": "keyword.other.$millisecond.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$minute\\b", + "captures": { + "0": { + "name": "keyword.other.$minute.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$mod\\b", + "captures": { + "0": { + "name": "keyword.other.$mod.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$month\\b", + "captures": { + "0": { + "name": "keyword.other.$month.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$multiply\\b", + "captures": { + "0": { + "name": "keyword.other.$multiply.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$new\\b", + "captures": { + "0": { + "name": "keyword.other.$new.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$not\\b", + "captures": { + "0": { + "name": "keyword.other.$not.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$objectToArray\\b", + "captures": { + "0": { + "name": "keyword.other.$objectToArray.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$or\\b", + "captures": { + "0": { + "name": "keyword.other.$or.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$pow\\b", + "captures": { + "0": { + "name": "keyword.other.$pow.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$range\\b", + "captures": { + "0": { + "name": "keyword.other.$range.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$reduce\\b", + "captures": { + "0": { + "name": "keyword.other.$reduce.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$regexFind\\b", + "captures": { + "0": { + "name": "keyword.other.$regexFind.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$regexFindAll\\b", + "captures": { + "0": { + "name": "keyword.other.$regexFindAll.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$regexMatch\\b", + "captures": { + "0": { + "name": "keyword.other.$regexMatch.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$replaceAll\\b", + "captures": { + "0": { + "name": "keyword.other.$replaceAll.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$replaceOne\\b", + "captures": { + "0": { + "name": "keyword.other.$replaceOne.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$reverseArray\\b", + "captures": { + "0": { + "name": "keyword.other.$reverseArray.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$second\\b", + "captures": { + "0": { + "name": "keyword.other.$second.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$setDifference\\b", + "captures": { + "0": { + "name": "keyword.other.$setDifference.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$setEquals\\b", + "captures": { + "0": { + "name": "keyword.other.$setEquals.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$setIntersection\\b", + "captures": { + "0": { + "name": "keyword.other.$setIntersection.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$setIsSubset\\b", + "captures": { + "0": { + "name": "keyword.other.$setIsSubset.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$setUnion\\b", + "captures": { + "0": { + "name": "keyword.other.$setUnion.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$size\\b", + "captures": { + "0": { + "name": "keyword.other.$size.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$slice\\b", + "captures": { + "0": { + "name": "keyword.other.$slice.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$sortArray\\b", + "captures": { + "0": { + "name": "keyword.other.$sortArray.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$split\\b", + "captures": { + "0": { + "name": "keyword.other.$split.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$sqrt\\b", + "captures": { + "0": { + "name": "keyword.other.$sqrt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$strcasecmp\\b", + "captures": { + "0": { + "name": "keyword.other.$strcasecmp.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$strLenBytes\\b", + "captures": { + "0": { + "name": "keyword.other.$strLenBytes.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$strLenCP\\b", + "captures": { + "0": { + "name": "keyword.other.$strLenCP.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$substr\\b", + "captures": { + "0": { + "name": "keyword.other.$substr.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$substrBytes\\b", + "captures": { + "0": { + "name": "keyword.other.$substrBytes.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$substrCP\\b", + "captures": { + "0": { + "name": "keyword.other.$substrCP.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$subtract\\b", + "captures": { + "0": { + "name": "keyword.other.$subtract.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$switch\\b", + "captures": { + "0": { + "name": "keyword.other.$switch.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toLower\\b", + "captures": { + "0": { + "name": "keyword.other.$toLower.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$toUpper\\b", + "captures": { + "0": { + "name": "keyword.other.$toUpper.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$tsSecond\\b", + "captures": { + "0": { + "name": "keyword.other.$tsSecond.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$tsIncrement\\b", + "captures": { + "0": { + "name": "keyword.other.$tsIncrement.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$trunc\\b", + "captures": { + "0": { + "name": "keyword.other.$trunc.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$type\\b", + "captures": { + "0": { + "name": "keyword.other.$type.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$week\\b", + "captures": { + "0": { + "name": "keyword.other.$week.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$year\\b", + "captures": { + "0": { + "name": "keyword.other.$year.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$zip\\b", + "captures": { + "0": { + "name": "keyword.other.$zip.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitAnd\\b", + "captures": { + "0": { + "name": "keyword.other.$bitAnd.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitOr\\b", + "captures": { + "0": { + "name": "keyword.other.$bitOr.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitXor\\b", + "captures": { + "0": { + "name": "keyword.other.$bitXor.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitNot\\b", + "captures": { + "0": { + "name": "keyword.other.$bitNot.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$all\\b", + "captures": { + "0": { + "name": "keyword.other.$all.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$and\\b", + "captures": { + "0": { + "name": "keyword.other.$and.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitsAllClear\\b", + "captures": { + "0": { + "name": "keyword.other.$bitsAllClear.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitsAllSet\\b", + "captures": { + "0": { + "name": "keyword.other.$bitsAllSet.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitsAnyClear\\b", + "captures": { + "0": { + "name": "keyword.other.$bitsAnyClear.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bitsAnySet\\b", + "captures": { + "0": { + "name": "keyword.other.$bitsAnySet.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$comment\\b", + "captures": { + "0": { + "name": "keyword.other.$comment.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$elemMatch\\b", + "captures": { + "0": { + "name": "keyword.other.$elemMatch.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$eq\\b", + "captures": { + "0": { + "name": "keyword.other.$eq.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$exists\\b", + "captures": { + "0": { + "name": "keyword.other.$exists.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$expr\\b", + "captures": { + "0": { + "name": "keyword.other.$expr.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$geoIntersects\\b", + "captures": { + "0": { + "name": "keyword.other.$geoIntersects.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$geoWithin\\b", + "captures": { + "0": { + "name": "keyword.other.$geoWithin.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$gt\\b", + "captures": { + "0": { + "name": "keyword.other.$gt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$gte\\b", + "captures": { + "0": { + "name": "keyword.other.$gte.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$in\\b", + "captures": { + "0": { + "name": "keyword.other.$in.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$jsonSchema\\b", + "captures": { + "0": { + "name": "keyword.other.$jsonSchema.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$lt\\b", + "captures": { + "0": { + "name": "keyword.other.$lt.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$lte\\b", + "captures": { + "0": { + "name": "keyword.other.$lte.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$mod\\b", + "captures": { + "0": { + "name": "keyword.other.$mod.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$ne\\b", + "captures": { + "0": { + "name": "keyword.other.$ne.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$near\\b", + "captures": { + "0": { + "name": "keyword.other.$near.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$nearSphere\\b", + "captures": { + "0": { + "name": "keyword.other.$nearSphere.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$nin\\b", + "captures": { + "0": { + "name": "keyword.other.$nin.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$not\\b", + "captures": { + "0": { + "name": "keyword.other.$not.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$nor\\b", + "captures": { + "0": { + "name": "keyword.other.$nor.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$or\\b", + "captures": { + "0": { + "name": "keyword.other.$or.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$regex\\b", + "captures": { + "0": { + "name": "keyword.other.$regex.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$size\\b", + "captures": { + "0": { + "name": "keyword.other.$size.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$slice\\b", + "captures": { + "0": { + "name": "keyword.other.$slice.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$text\\b", + "captures": { + "0": { + "name": "keyword.other.$text.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$type\\b", + "captures": { + "0": { + "name": "keyword.other.$type.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$where\\b", + "captures": { + "0": { + "name": "keyword.other.$where.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$addFields\\b", + "captures": { + "0": { + "name": "keyword.other.$addFields.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bucket\\b", + "captures": { + "0": { + "name": "keyword.other.$bucket.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$bucketAuto\\b", + "captures": { + "0": { + "name": "keyword.other.$bucketAuto.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$collStats\\b", + "captures": { + "0": { + "name": "keyword.other.$collStats.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$count\\b", + "captures": { + "0": { + "name": "keyword.other.$count.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$densify\\b", + "captures": { + "0": { + "name": "keyword.other.$densify.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$documents\\b", + "captures": { + "0": { + "name": "keyword.other.$documents.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$facet\\b", + "captures": { + "0": { + "name": "keyword.other.$facet.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$fill\\b", + "captures": { + "0": { + "name": "keyword.other.$fill.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$geoNear\\b", + "captures": { + "0": { + "name": "keyword.other.$geoNear.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$graphLookup\\b", + "captures": { + "0": { + "name": "keyword.other.$graphLookup.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$group\\b", + "captures": { + "0": { + "name": "keyword.other.$group.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$indexStats\\b", + "captures": { + "0": { + "name": "keyword.other.$indexStats.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$limit\\b", + "captures": { + "0": { + "name": "keyword.other.$limit.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$lookup\\b", + "captures": { + "0": { + "name": "keyword.other.$lookup.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$match\\b", + "captures": { + "0": { + "name": "keyword.other.$match.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$merge\\b", + "captures": { + "0": { + "name": "keyword.other.$merge.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$merge\\b", + "captures": { + "0": { + "name": "keyword.other.$merge.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$out\\b", + "captures": { + "0": { + "name": "keyword.other.$out.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$out\\b", + "captures": { + "0": { + "name": "keyword.other.$out.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$project\\b", + "captures": { + "0": { + "name": "keyword.other.$project.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$redact\\b", + "captures": { + "0": { + "name": "keyword.other.$redact.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$replaceWith\\b", + "captures": { + "0": { + "name": "keyword.other.$replaceWith.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$replaceRoot\\b", + "captures": { + "0": { + "name": "keyword.other.$replaceRoot.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$sample\\b", + "captures": { + "0": { + "name": "keyword.other.$sample.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$search\\b", + "captures": { + "0": { + "name": "keyword.other.$search.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$searchMeta\\b", + "captures": { + "0": { + "name": "keyword.other.$searchMeta.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$set\\b", + "captures": { + "0": { + "name": "keyword.other.$set.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$setWindowFields\\b", + "captures": { + "0": { + "name": "keyword.other.$setWindowFields.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$skip\\b", + "captures": { + "0": { + "name": "keyword.other.$skip.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$sort\\b", + "captures": { + "0": { + "name": "keyword.other.$sort.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$sortByCount\\b", + "captures": { + "0": { + "name": "keyword.other.$sortByCount.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$unionWith\\b", + "captures": { + "0": { + "name": "keyword.other.$unionWith.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$unset\\b", + "captures": { + "0": { + "name": "keyword.other.$unset.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$unwind\\b", + "captures": { + "0": { + "name": "keyword.other.$unwind.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$changeStream\\b", + "captures": { + "0": { + "name": "keyword.other.$changeStream.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$currentOp\\b", + "captures": { + "0": { + "name": "keyword.other.$currentOp.mongodb" + } + } + }, + { + "name": "meta.object.member.mongodb", + "match": "\\$listLocalSessions\\b", + "captures": { + "0": { + "name": "keyword.other.$listLocalSessions.mongodb" + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 144c43d8b..869b9fd61 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,9 +2,9 @@ "compilerOptions": { "module": "commonjs", "noImplicitAny": false, - "target": "es2018", + "target": "es2019", "outDir": "out", - "lib": ["dom", "es2018"], + "lib": ["dom", "es2019"], "types": ["node"], "jsx": "react", "sourceMap": true,