diff --git a/package-lock.json b/package-lock.json index 9831e0cc5ba..ef304280621 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,6 +70,7 @@ "htmlparser2": "9.0.0", "jsx-ast-utils": "3.3.5", "lodash.clone": "4.5.0", + "minimatch": "^9.0.3", "module-alias": "2.2.3", "postcss": "8.4.31", "postcss-html": "0.36.0", @@ -82,6 +83,7 @@ "scslre": "0.2.0", "stylelint": "15.10.0", "tmp": "0.2.1", + "type-fest": "4.6.0", "typescript": "5.1.6", "vue-eslint-parser": "9.3.0", "yaml": "2.3.1" @@ -2064,6 +2066,16 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "inBundle": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.21.0", "inBundle": true, @@ -2078,6 +2090,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "inBundle": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "inBundle": true, @@ -2110,6 +2134,28 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "inBundle": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "inBundle": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "inBundle": true, @@ -3589,6 +3635,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://repox.jfrog.io/repox/api/npm/npm/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "inBundle": true, @@ -4026,8 +4081,9 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "inBundle": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "inBundle": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -4094,12 +4150,11 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "inBundle": true, - "license": "MIT", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -4395,8 +4450,9 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "inBundle": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "inBundle": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -5454,12 +5510,34 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "inBundle": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://repox.jfrog.io/repox/api/npm/npm/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "inBundle": true }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "inBundle": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-react": { "version": "7.33.2", "inBundle": true, @@ -5500,6 +5578,16 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "inBundle": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "inBundle": true, @@ -5511,6 +5599,18 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "inBundle": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.4", "inBundle": true, @@ -5581,6 +5681,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "inBundle": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "inBundle": true, @@ -5671,6 +5781,18 @@ "node": ">=8" } }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "inBundle": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "inBundle": true, @@ -6319,6 +6441,28 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "inBundle": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "inBundle": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/global-modules": { "version": "2.0.0", "inBundle": true, @@ -9185,14 +9329,17 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "inBundle": true, - "license": "ISC", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -9269,6 +9416,28 @@ "node": ">=8" } }, + "node_modules/multimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/multimatch/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/nanoid": { "version": "3.3.6", "funding": [ @@ -11577,6 +11746,28 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-table": { "version": "0.2.0", "inBundle": true, @@ -11804,14 +11995,11 @@ } }, "node_modules/type-fest": { - "version": "0.21.3", - "dev": true, - "license": "(MIT OR CC0-1.0)", + "version": "4.6.0", + "resolved": "https://repox.jfrog.io/repox/api/npm/npm/type-fest/-/type-fest-4.6.0.tgz", + "integrity": "sha512-rLjWJzQFOq4xw7MgJrCZ6T1jIOvvYElXT12r+y0CC6u67hegDHaxcPqb2fZHOGlqxugGQPNB1EnTezjBetkwkw==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16" } }, "node_modules/type-is": { @@ -11907,28 +12095,6 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" } }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { "version": "5.1.6", "inBundle": true, @@ -13489,12 +13655,29 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "globals": { "version": "13.21.0", "requires": { "type-fest": "^0.20.2" } }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, "type-fest": { "version": "0.20.2" } @@ -13509,6 +13692,25 @@ "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.5" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "@humanwhocodes/module-importer": { @@ -14461,6 +14663,14 @@ "dev": true, "requires": { "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://repox.jfrog.io/repox/api/npm/npm/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } } }, "ansi-regex": { @@ -14740,7 +14950,9 @@ } }, "balanced-match": { - "version": "1.0.2" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", @@ -14783,10 +14995,11 @@ } }, "brace-expansion": { - "version": "1.1.11", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "braces": { @@ -14962,7 +15175,9 @@ "dev": true }, "concat-map": { - "version": "0.0.1" + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "content-disposition": { "version": "0.5.4", @@ -15630,6 +15845,15 @@ "color-convert": "^2.0.1" } }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "chalk": { "version": "4.1.2", "requires": { @@ -15668,6 +15892,14 @@ "has-flag": { "version": "4.0.0" }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, "supports-color": { "version": "7.2.0", "requires": { @@ -15702,10 +15934,27 @@ "semver": "^6.3.0" }, "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "emoji-regex": { "version": "9.2.2", "resolved": "https://repox.jfrog.io/repox/api/npm/npm/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } } } }, @@ -15730,12 +15979,29 @@ "string.prototype.matchall": "^4.0.8" }, "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "doctrine": { "version": "2.1.0", "requires": { "esutils": "^2.0.2" } }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, "resolve": { "version": "2.0.0-next.4", "requires": { @@ -16132,6 +16398,25 @@ "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "glob-parent": { @@ -17819,9 +18104,11 @@ "version": "1.0.1" }, "minimatch": { - "version": "3.1.2", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" } }, "minimist": { @@ -17865,6 +18152,27 @@ "array-union": "^2.1.0", "arrify": "^2.0.1", "minimatch": "^3.0.4" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "nanoid": { @@ -19189,6 +19497,27 @@ "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "text-table": { @@ -19304,8 +19633,9 @@ "dev": true }, "type-fest": { - "version": "0.21.3", - "dev": true + "version": "4.6.0", + "resolved": "https://repox.jfrog.io/repox/api/npm/npm/type-fest/-/type-fest-4.6.0.tgz", + "integrity": "sha512-rLjWJzQFOq4xw7MgJrCZ6T1jIOvvYElXT12r+y0CC6u67hegDHaxcPqb2fZHOGlqxugGQPNB1EnTezjBetkwkw==" }, "type-is": { "version": "1.6.18", @@ -19357,22 +19687,6 @@ "marked": "^4.3.0", "minimatch": "^9.0.0", "shiki": "^0.14.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } } }, "typescript": { diff --git a/package.json b/package.json index 767fcba94f5..0646088bc8c 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "htmlparser2": "9.0.0", "jsx-ast-utils": "3.3.5", "lodash.clone": "4.5.0", + "minimatch": "^9.0.3", "module-alias": "2.2.3", "postcss": "8.4.31", "postcss-html": "0.36.0", @@ -102,6 +103,7 @@ "scslre": "0.2.0", "stylelint": "15.10.0", "tmp": "0.2.1", + "type-fest": "4.6.0", "typescript": "5.1.6", "vue-eslint-parser": "9.3.0", "yaml": "2.3.1" @@ -129,6 +131,7 @@ "htmlparser2", "jsx-ast-utils", "lodash.clone", + "minimatch", "module-alias", "postcss", "postcss-html", diff --git a/packages/bridge/src/worker.js b/packages/bridge/src/worker.js index 8a2a3ebea3c..69bd44b4651 100644 --- a/packages/bridge/src/worker.js +++ b/packages/bridge/src/worker.js @@ -29,6 +29,7 @@ const { deleteProgram, initializeLinter, writeTSConfigFile, + searchPackageJsonFiles, } = require('@sonar/jsts'); const { readFile, setContext } = require('@sonar/shared/helpers'); const { analyzeCSS } = require('@sonar/css'); @@ -136,8 +137,9 @@ if (parentPort) { } case 'on-init-linter': { - const { rules, environments, globals, linterId } = data; + const { rules, environments, globals, linterId, baseDir, exclusions } = data; initializeLinter(rules, environments, globals, linterId); + await searchPackageJsonFiles(baseDir, exclusions); parentThread.postMessage({ type: 'success', result: 'OK!' }); break; } diff --git a/packages/jsts/src/builders/build.ts b/packages/jsts/src/builders/build.ts index 83873c9e575..64097d3fe7b 100644 --- a/packages/jsts/src/builders/build.ts +++ b/packages/jsts/src/builders/build.ts @@ -22,6 +22,7 @@ import { JsTsAnalysisInput } from '../analysis'; import { buildParserOptions, parseForESLint, parsers } from '../parsers'; import { getProgramById } from '../program'; import { Linter } from 'eslint'; +import { getNearestPackageJson } from '../dependencies'; /** * Builds an ESLint SourceCode for JavaScript / TypeScript @@ -35,6 +36,7 @@ import { Linter } from 'eslint'; */ export function buildSourceCode(input: JsTsAnalysisInput, language: JsTsLanguage) { const vueFile = isVueFile(input.filePath); + const packageJson = getNearestPackageJson(input.filePath); if (shouldUseTypescriptParser(language)) { const options: Linter.ParserOptions = { @@ -51,6 +53,7 @@ export function buildSourceCode(input: JsTsAnalysisInput, language: JsTsLanguage input.fileContent, vueFile ? parsers.vuejs.parse : parsers.typescript.parse, buildParserOptions(options, false), + packageJson?.contents, ); } catch (error) { debug(`Failed to parse ${input.filePath} with TypeScript parser: ${error.message}`); @@ -66,6 +69,7 @@ export function buildSourceCode(input: JsTsAnalysisInput, language: JsTsLanguage input.fileContent, vueFile ? parsers.vuejs.parse : parsers.javascript.parse, buildParserOptions({ parser: vueFile ? parsers.javascript.parser : undefined }, true), + packageJson?.contents, ); } catch (error) { debug(`Failed to parse ${input.filePath} with Javascript parser: ${error.message}`); @@ -80,6 +84,7 @@ export function buildSourceCode(input: JsTsAnalysisInput, language: JsTsLanguage input.fileContent, parsers.javascript.parse, buildParserOptions({ sourceType: 'script' }, true), + packageJson?.contents, ); } catch (error) { debug( diff --git a/packages/jsts/src/dependencies/index.ts b/packages/jsts/src/dependencies/index.ts new file mode 100644 index 00000000000..dfb33070a0e --- /dev/null +++ b/packages/jsts/src/dependencies/index.ts @@ -0,0 +1,20 @@ +/* + * SonarQube JavaScript Plugin + * Copyright (C) 2011-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +export * from './package-json'; diff --git a/packages/jsts/src/dependencies/package-json/index.ts b/packages/jsts/src/dependencies/package-json/index.ts new file mode 100644 index 00000000000..cc733eb0823 --- /dev/null +++ b/packages/jsts/src/dependencies/package-json/index.ts @@ -0,0 +1,37 @@ +/* + * SonarQube JavaScript Plugin + * Copyright (C) 2011-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { PackageJsons } from './project-package-json'; + +const PackageJsonsByBaseDir = new PackageJsons(); + +async function searchPackageJsonFiles(baseDir: string, exclusions: string[]) { + await PackageJsonsByBaseDir.searchPackageJsonFiles(baseDir, exclusions); +} + +function getNearestPackageJson(file: string) { + return PackageJsonsByBaseDir.getPackageJsonForFile(file); +} + +function getAllPackageJsons() { + return PackageJsonsByBaseDir.db; +} + +export { searchPackageJsonFiles, getNearestPackageJson, getAllPackageJsons, PackageJsonsByBaseDir }; diff --git a/packages/jsts/src/dependencies/package-json/project-package-json.ts b/packages/jsts/src/dependencies/package-json/project-package-json.ts new file mode 100644 index 00000000000..e49a59006eb --- /dev/null +++ b/packages/jsts/src/dependencies/package-json/project-package-json.ts @@ -0,0 +1,96 @@ +/* + * SonarQube JavaScript Plugin + * Copyright (C) 2011-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import fs from 'fs/promises'; +import path from 'path'; +import { toUnixPath, debug, error, readFile } from '@sonar/shared/helpers'; +import { PackageJson as PJ } from 'type-fest'; +import { Minimatch } from 'minimatch'; + +const PACKAGE_JSON = 'package.json'; + +// Patterns enforced to be ignored no matter what the user configures on sonar.properties +const IGNORED_PATTERNS = ['**/.scannerwork/**']; + +export interface PackageJson { + filename: string; + contents: PJ; +} + +export class PackageJsons { + readonly db: Map = new Map(); + + /** + * Look for package.json files in a given path and its child paths. + * node_modules is ignored + * + * @param dir parent folder where the search starts + * @param exclusions glob patterns to ignore while walking the tree + */ + async searchPackageJsonFiles(dir: string, exclusions: string[]) { + try { + const patterns = exclusions + .concat(IGNORED_PATTERNS) + .map(exclusion => new Minimatch(exclusion)); + await this.walkDirectory(path.posix.normalize(toUnixPath(dir)), patterns); + } catch (e) { + error(`Error while searching for package.json files: ${e}`); + } + } + + async walkDirectory(dir: string, ignoredPatterns: Minimatch[]) { + const files = await fs.readdir(dir, { withFileTypes: true }); + for (const file of files) { + const filename = path.posix.join(dir, file.name); + if (ignoredPatterns.some(pattern => pattern.match(filename))) { + continue; // is ignored pattern + } + if (file.isDirectory()) { + await this.walkDirectory(filename, ignoredPatterns); + } else if (file.name.toLowerCase() === PACKAGE_JSON && !file.isDirectory()) { + try { + debug(`Found package.json: ${filename}`); + const contents = JSON.parse(await readFile(filename)); + this.db.set(dir, { filename, contents }); + } catch (e) { + debug(`Error reading file ${filename}: ${e}`); + } + } + } + } + /** + * Given a filename, find the nearest package.json + * + * @param file source file for which we need a package.json + */ + getPackageJsonForFile(file: string) { + if (this.db.size === 0) { + return null; + } + let currentDir = path.posix.dirname(path.posix.normalize(toUnixPath(file))); + do { + const packageJson = this.db.get(currentDir); + if (packageJson) { + return packageJson; + } + currentDir = path.posix.dirname(currentDir); + } while (currentDir !== path.posix.dirname(currentDir)); + return null; + } +} diff --git a/packages/jsts/src/index.ts b/packages/jsts/src/index.ts index 065fc4d6020..caf4bfbd584 100644 --- a/packages/jsts/src/index.ts +++ b/packages/jsts/src/index.ts @@ -19,6 +19,7 @@ */ export * from './analysis'; export * from './builders'; +export * from './dependencies'; export * from './linter'; export * from './parsers'; export * from './program'; diff --git a/packages/jsts/src/parsers/parse.ts b/packages/jsts/src/parsers/parse.ts index 955dc59ae02..7e31bb5aec3 100644 --- a/packages/jsts/src/parsers/parse.ts +++ b/packages/jsts/src/parsers/parse.ts @@ -20,21 +20,30 @@ import { APIError } from '@sonar/shared/errors'; import { SourceCode } from 'eslint'; import { ParseFunction } from './eslint'; +import { PackageJson } from 'type-fest'; /** * Parses a JavaScript / TypeScript analysis input with an ESLint-based parser * @param code the JavaScript / TypeScript code to parse * @param parse the ESLint parsing function to use for parsing * @param options the ESLint parser options + * @param packageJson package.json contents containing dependencies * @returns the parsed source code */ -export function parseForESLint(code: string, parse: ParseFunction, options: {}): SourceCode { +export function parseForESLint( + code: string, + parse: ParseFunction, + options: {}, + packageJson?: PackageJson, +): SourceCode { try { const result = parse(code, options); + const parserServices = result.services || {}; + parserServices.packageJson = packageJson; return new SourceCode({ ...result, text: code, - parserServices: result.services, + parserServices, }); } catch ({ lineNumber, message }) { if (message.startsWith('Debug Failure')) { diff --git a/packages/jsts/tests/analysis/analyzer.test.ts b/packages/jsts/tests/analysis/analyzer.test.ts index eef5d31a4ad..8bbdfda75cd 100644 --- a/packages/jsts/tests/analysis/analyzer.test.ts +++ b/packages/jsts/tests/analysis/analyzer.test.ts @@ -25,12 +25,14 @@ import { analyzeJSTS, JsTsAnalysisOutput, createAndSaveProgram, + searchPackageJsonFiles, } from '../../src'; import { APIError } from '@sonar/shared/errors'; -import { jsTsInput } from '../tools'; - +import { jsTsInput, parseJavaScriptSourceFile } from '../tools'; +import { Linter, Rule } from 'eslint'; describe('analyzeJSTS', () => { beforeEach(() => { + jest.resetModules(); setContext({ workDir: '/tmp/dir', shouldUseTypeScriptParserForJS: false, @@ -893,4 +895,51 @@ describe('analyzeJSTS', () => { APIError.parsingError('Unexpected token (3:0)', { line: 3 }), ); }); + + it('package.json should be available in rule context', async () => { + const baseDir = path.join(__dirname, 'fixtures', 'package-json'); + await searchPackageJsonFiles(baseDir, []); + + const linter = new Linter(); + linter.defineRule('custom-rule-file', { + create(context) { + return { + CallExpression(node) { + expect(context.parserServices.packageJson).toBeDefined(); + expect(context.parserServices.packageJson.name).toEqual('test-module'); + context.report({ + node: node.callee, + message: 'call', + }); + }, + }; + }, + } as Rule.RuleModule); + + const filePath = path.join(baseDir, 'custom.js'); + const sourceCode = await parseJavaScriptSourceFile(filePath); + expect(sourceCode.parserServices.packageJson).toBeDefined(); + expect(sourceCode.parserServices.packageJson.name).toEqual('test-module'); + + const issues = linter.verify( + sourceCode, + { rules: { 'custom-rule-file': 'error' } }, + { filename: filePath, allowInlineConfig: false }, + ); + expect(issues).toHaveLength(1); + expect(issues[0].message).toEqual('call'); + + const vueFilePath = path.join(baseDir, 'code.vue'); + const vueSourceCode = await parseJavaScriptSourceFile(vueFilePath); + expect(vueSourceCode.parserServices.packageJson).toBeDefined(); + expect(vueSourceCode.parserServices.packageJson.name).toEqual('test-module'); + + const vueIssues = linter.verify( + vueSourceCode, + { rules: { 'custom-rule-file': 'error' } }, + { filename: vueFilePath, allowInlineConfig: false }, + ); + expect(vueIssues).toHaveLength(1); + expect(vueIssues[0].message).toEqual('call'); + }); }); diff --git a/packages/jsts/tests/analysis/fixtures/package-json/code.vue b/packages/jsts/tests/analysis/fixtures/package-json/code.vue new file mode 100644 index 00000000000..a20460b18ff --- /dev/null +++ b/packages/jsts/tests/analysis/fixtures/package-json/code.vue @@ -0,0 +1,3 @@ + diff --git a/packages/jsts/tests/analysis/fixtures/package-json/custom.js b/packages/jsts/tests/analysis/fixtures/package-json/custom.js new file mode 100644 index 00000000000..eb28ef4401b --- /dev/null +++ b/packages/jsts/tests/analysis/fixtures/package-json/custom.js @@ -0,0 +1 @@ +foo() diff --git a/packages/jsts/tests/analysis/fixtures/package-json/package.json b/packages/jsts/tests/analysis/fixtures/package-json/package.json new file mode 100644 index 00000000000..ae09dbe552b --- /dev/null +++ b/packages/jsts/tests/analysis/fixtures/package-json/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-module", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/builders/build.test.ts b/packages/jsts/tests/builders/build.test.ts index 4af2e365545..ad62bad4be5 100644 --- a/packages/jsts/tests/builders/build.test.ts +++ b/packages/jsts/tests/builders/build.test.ts @@ -17,8 +17,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { setContext } from '@sonar/shared/helpers'; -import { buildSourceCode } from '../../src'; +import { setContext, toUnixPath } from '@sonar/shared/helpers'; +import { buildSourceCode, searchPackageJsonFiles } from '../../src'; import path from 'path'; import { AST } from 'vue-eslint-parser'; import { jsTsInput } from '../tools'; @@ -289,4 +289,19 @@ describe('buildSourceCode', () => { const log = `DEBUG Failed to parse ${filePath} with TypeScript parser: Expression expected.`; expect(console.log).toHaveBeenCalledWith(log); }); + + it('should include package.json contents in SourceCode', async () => { + console.log = jest.fn(); + const baseDir = path.join(__dirname, 'fixtures', 'build'); + const filePath = path.join(baseDir, 'file.ts'); + const packageJson = path.join(baseDir, 'package.json'); + await searchPackageJsonFiles(baseDir, []); + const log = `DEBUG Found package.json: ${toUnixPath(packageJson)}`; + expect(console.log).toHaveBeenCalledWith(log); + + const result = buildSourceCode(await jsTsInput({ filePath }), 'ts'); + + expect(result.parserServices.packageJson).toBeDefined(); + expect(result.parserServices.packageJson.name).toEqual('test-build-module'); + }); }); diff --git a/packages/jsts/tests/builders/fixtures/build/package.json b/packages/jsts/tests/builders/fixtures/build/package.json new file mode 100644 index 00000000000..bc2095216e3 --- /dev/null +++ b/packages/jsts/tests/builders/fixtures/build/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-build-module", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/fixtures/moduleA/package.json b/packages/jsts/tests/dependencies/fixtures/moduleA/package.json new file mode 100644 index 00000000000..a94ef6996d3 --- /dev/null +++ b/packages/jsts/tests/dependencies/fixtures/moduleA/package.json @@ -0,0 +1,5 @@ +{ + "name": "module-a", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/fixtures/moduleA/submoduleA/package.json b/packages/jsts/tests/dependencies/fixtures/moduleA/submoduleA/package.json new file mode 100644 index 00000000000..c4260afda57 --- /dev/null +++ b/packages/jsts/tests/dependencies/fixtures/moduleA/submoduleA/package.json @@ -0,0 +1,5 @@ +{ + "name": "module-a-submodule-a", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/fixtures/moduleA/submoduleB/package.json b/packages/jsts/tests/dependencies/fixtures/moduleA/submoduleB/package.json new file mode 100644 index 00000000000..c1dcc4f6c17 --- /dev/null +++ b/packages/jsts/tests/dependencies/fixtures/moduleA/submoduleB/package.json @@ -0,0 +1,5 @@ +{ + "name": "module-a-submodule-b", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/fixtures/moduleB/package.json b/packages/jsts/tests/dependencies/fixtures/moduleB/package.json new file mode 100644 index 00000000000..fff9ec11773 --- /dev/null +++ b/packages/jsts/tests/dependencies/fixtures/moduleB/package.json @@ -0,0 +1,5 @@ +{ + "name": "myProject", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/fixtures/moduleB/submoduleA/package.json b/packages/jsts/tests/dependencies/fixtures/moduleB/submoduleA/package.json new file mode 100644 index 00000000000..510b65e3ea1 --- /dev/null +++ b/packages/jsts/tests/dependencies/fixtures/moduleB/submoduleA/package.json @@ -0,0 +1,5 @@ +{ + "name": "module-b-submodule-a", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/fixtures/moduleB/submoduleB/package.json b/packages/jsts/tests/dependencies/fixtures/moduleB/submoduleB/package.json new file mode 100644 index 00000000000..5a3cecea18c --- /dev/null +++ b/packages/jsts/tests/dependencies/fixtures/moduleB/submoduleB/package.json @@ -0,0 +1,5 @@ +{ + "name": "module-b-submodule-b", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/fixtures/package.json b/packages/jsts/tests/dependencies/fixtures/package.json new file mode 100644 index 00000000000..5fc21e32970 --- /dev/null +++ b/packages/jsts/tests/dependencies/fixtures/package.json @@ -0,0 +1,5 @@ +{ + "name": "module-b", + "version": "1.0.0", + "author": "Your Name " +} diff --git a/packages/jsts/tests/dependencies/index.test.ts b/packages/jsts/tests/dependencies/index.test.ts new file mode 100644 index 00000000000..e9e12f5f2a3 --- /dev/null +++ b/packages/jsts/tests/dependencies/index.test.ts @@ -0,0 +1,140 @@ +/* + * SonarQube JavaScript Plugin + * Copyright (C) 2011-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import path from 'path'; +import { toUnixPath } from '@sonar/shared/helpers'; +import { + searchPackageJsonFiles, + getAllPackageJsons, + getNearestPackageJson, + PackageJsonsByBaseDir, +} from '@sonar/jsts'; + +describe('initialize package.json files', () => { + beforeEach(() => { + jest.resetModules(); + getAllPackageJsons().clear(); + }); + + it('should find all package.json files', async () => { + const baseDir = path.posix.join(toUnixPath(__dirname), 'fixtures'); + await searchPackageJsonFiles(baseDir, []); + expect(getAllPackageJsons().size).toEqual(7); + + expect(getNearestPackageJson(path.posix.join(baseDir, 'index.js')).filename).toEqual( + toUnixPath(path.posix.join(baseDir, 'package.json')), + ); + expect(getNearestPackageJson(path.posix.join(baseDir, 'moduleA', 'index.js')).filename).toEqual( + toUnixPath(path.posix.join(baseDir, 'moduleA', 'package.json')), + ); + expect( + getNearestPackageJson(path.posix.join(baseDir, 'moduleA', 'submoduleA', 'index.js')).filename, + ).toEqual(toUnixPath(path.posix.join(baseDir, 'moduleA', 'submoduleA', 'package.json'))); + expect( + getNearestPackageJson(path.posix.join(baseDir, 'moduleA', 'submoduleB', 'index.js')).filename, + ).toEqual(toUnixPath(path.posix.join(baseDir, 'moduleA', 'submoduleB', 'package.json'))); + expect(getNearestPackageJson(path.posix.join(baseDir, 'moduleB', 'index.js')).filename).toEqual( + toUnixPath(path.posix.join(baseDir, 'moduleB', 'package.json')), + ); + expect( + getNearestPackageJson(path.posix.join(baseDir, 'moduleB', 'submoduleA', 'index.js')).filename, + ).toEqual(toUnixPath(path.posix.join(baseDir, 'moduleB', 'submoduleA', 'package.json'))); + expect( + getNearestPackageJson(path.posix.join(baseDir, 'moduleB', 'submoduleB', 'index.js')).filename, + ).toEqual(toUnixPath(path.posix.join(baseDir, 'moduleB', 'submoduleB', 'package.json'))); + expect( + getNearestPackageJson( + path.posix.join( + __dirname, + 'fixtures', + 'moduleB', + 'submoduleB', + 'subfolder1', + 'subfolder2', + 'subfolder3', + 'index.js', + ), + ).filename, + ).toEqual(toUnixPath(path.posix.join(baseDir, 'moduleB', 'submoduleB', 'package.json'))); + }); + + it('should ignore package.json files from ignored patterns', async () => { + const baseDir = path.posix.join(toUnixPath(__dirname), 'fixtures'); + + await searchPackageJsonFiles(baseDir, ['**/moduleA/**']); + expect(getAllPackageJsons().size).toEqual(4); + const packageJsons = [ + ['package.json'], + ['moduleB', 'package.json'], + ['moduleB', 'submoduleA', 'package.json'], + ['moduleB', 'submoduleB', 'package.json'], + ]; + expect(getAllPackageJsons()).toEqual( + new Map( + packageJsons.map(packageJson => { + const filename = path.posix.join(baseDir, ...packageJson); + return [path.posix.dirname(filename), { filename, contents: expect.any(Object) }]; + }), + ), + ); + + getAllPackageJsons().clear(); + await searchPackageJsonFiles(baseDir, ['**/module*/**']); + expect(getAllPackageJsons().size).toEqual(1); + expect(getAllPackageJsons()).toEqual( + new Map([ + [ + baseDir, + { filename: path.posix.join(baseDir, 'package.json'), contents: expect.any(Object) }, + ], + ]), + ); + }); + + it('should return null when no package.json are in the DB or none exist in the file tree', async () => { + const baseDir = path.posix.join(toUnixPath(__dirname), 'fixtures'); + + expect(getAllPackageJsons().size).toEqual(0); + expect( + getNearestPackageJson(path.posix.join(baseDir, '..', 'another-module', 'index.js')), + ).toBeNull(); + + await searchPackageJsonFiles(baseDir, ['']); + expect(getAllPackageJsons().size).toEqual(7); + expect( + getNearestPackageJson(path.posix.join(baseDir, '..', 'another-module', 'index.js')), + ).toBeNull(); + }); + + it('should log error when cannot access baseDir', async () => { + const baseDir = path.posix.join(toUnixPath(__dirname), 'fixtures'); + + console.error = jest.fn(); + + jest.spyOn(PackageJsonsByBaseDir, 'walkDirectory').mockImplementation(dir => { + throw Error(`Cannot access ${dir}`); + }); + + await searchPackageJsonFiles(baseDir, ['']); + expect(console.error).toHaveBeenCalledWith( + `Error while searching for package.json files: Error: Cannot access ${baseDir}`, + ); + }); +}); diff --git a/packages/shared/src/helpers/files.ts b/packages/shared/src/helpers/files.ts index c6f0e927712..4edc80517a7 100644 --- a/packages/shared/src/helpers/files.ts +++ b/packages/shared/src/helpers/files.ts @@ -86,7 +86,7 @@ export function stripBOM(str: string) { * @returns the converted path */ export function toUnixPath(path: string) { - return path.replace(/[\\/]+/g, '/').replace(/(\.\/)/, ''); + return path.replace(/[\\/]+/g, '/'); } /** diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractBridgeSensor.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractBridgeSensor.java index 113b3e73031..a9bf35fdfbb 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractBridgeSensor.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/AbstractBridgeSensor.java @@ -31,12 +31,14 @@ import org.sonar.plugins.javascript.JavaScriptPlugin; import org.sonar.plugins.javascript.bridge.cache.CacheStrategies; import org.sonar.plugins.javascript.nodejs.NodeCommandException; +import org.sonar.plugins.javascript.utils.Exclusions; public abstract class AbstractBridgeSensor implements Sensor { private static final Logger LOG = Loggers.get(AbstractBridgeSensor.class); protected final BridgeServer bridgeServer; + protected List exclusions; private final AnalysisWarningsWrapper analysisWarnings; final Monitoring monitoring; List environments; @@ -60,6 +62,7 @@ public void execute(SensorContext context) { monitoring.startSensor(context, this); CacheStrategies.reset(); this.context = context; + this.exclusions = Arrays.asList(Exclusions.getExcludedPaths(context.config())); this.contextUtils = new ContextUtils(context); environments = Arrays.asList(context.config().getStringArray(JavaScriptPlugin.ENVIRONMENTS)); globals = Arrays.asList(context.config().getStringArray(JavaScriptPlugin.GLOBALS)); diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java index 8a0c5c6a1b0..784356cf0f3 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServer.java @@ -41,7 +41,9 @@ void initLinter( List rules, List environments, List globals, - AnalysisMode analysisMode + AnalysisMode analysisMode, + String baseDir, + List exclusions ) throws IOException; AnalysisResponse analyzeJavaScript(JsAnalysisRequest request) throws IOException; diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java index ba10256987b..8281fa8f958 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/BridgeServerImpl.java @@ -239,6 +239,7 @@ private NodeCommand initNodeCommand(SensorContext context, File scriptFile, Stri nodeCommandBuilder .outputConsumer(outputConsumer) + .errorConsumer(LOG::error) .embeddedNode(embeddedNode) .pathResolver(bundle) .minNodeVersion(NodeDeprecationWarning.MIN_SUPPORTED_NODE_VERSION) @@ -312,16 +313,20 @@ public void initLinter( List rules, List environments, List globals, - AnalysisMode analysisMode + AnalysisMode analysisMode, + String baseDir, + List exclusions ) throws IOException { - initLinter(AnalysisMode.DEFAULT_LINTER_ID, rules, environments, globals); + initLinter(AnalysisMode.DEFAULT_LINTER_ID, rules, environments, globals, baseDir, exclusions); if (analysisMode == AnalysisMode.SKIP_UNCHANGED) { initLinter( AnalysisMode.UNCHANGED_LINTER_ID, AnalysisMode.getUnchangedFileRules(rules), environments, - globals + globals, + baseDir, + exclusions ); } } @@ -330,15 +335,20 @@ private void initLinter( String linterId, List rules, List environments, - List globals + List globals, + String baseDir, + List exclusions ) throws IOException { InitLinterRequest initLinterRequest = new InitLinterRequest( linterId, rules, environments, - globals + globals, + baseDir, + exclusions ); String request = GSON.toJson(initLinterRequest); + String response = request(request, "init-linter"); if (!"OK!".equals(response)) { throw new IllegalStateException("Failed to initialize linter"); @@ -588,17 +598,23 @@ static class InitLinterRequest { List rules; List environments; List globals; + String baseDir; + List exclusions; InitLinterRequest( String linterId, List rules, List environments, - List globals + List globals, + String baseDir, + List exclusions ) { this.linterId = linterId; this.rules = rules; this.environments = environments; this.globals = globals; + this.baseDir = baseDir; + this.exclusions = exclusions; } } diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/HtmlSensor.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/HtmlSensor.java index f88ad1325e7..04901782327 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/HtmlSensor.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/HtmlSensor.java @@ -77,7 +77,9 @@ protected void analyzeFiles(List inputFiles) throws IOException { AnalysisMode.getHtmlFileRules(checks.eslintRules()), environments, globals, - analysisMode + analysisMode, + context.fileSystem().baseDir().getAbsolutePath(), + exclusions ); for (var inputFile : inputFiles) { if (context.isCancelled()) { diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/JsTsSensor.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/JsTsSensor.java index 2ef56cf65df..813372a6541 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/JsTsSensor.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/JsTsSensor.java @@ -104,7 +104,14 @@ protected List getInputFiles() { @Override protected void analyzeFiles(List inputFiles) throws IOException { var analysisMode = AnalysisMode.getMode(context, checks.eslintRules()); - bridgeServer.initLinter(checks.eslintRules(), environments, globals, analysisMode); + bridgeServer.initLinter( + checks.eslintRules(), + environments, + globals, + analysisMode, + context.fileSystem().baseDir().getAbsolutePath(), + exclusions + ); SonarLintTypeCheckingChecker.checkOnce(javaScriptProjectChecker, context); var tsConfigs = TsConfigProvider.getTsConfigs( diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/YamlSensor.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/YamlSensor.java index 65cf12fa5a2..148ceea9d39 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/YamlSensor.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/bridge/YamlSensor.java @@ -76,7 +76,14 @@ protected void analyzeFiles(List inputFiles) throws IOException { var success = false; try { progressReport.start(inputFiles.size(), inputFiles.iterator().next().absolutePath()); - bridgeServer.initLinter(checks.eslintRules(), environments, globals, analysisMode); + bridgeServer.initLinter( + checks.eslintRules(), + environments, + globals, + analysisMode, + context.fileSystem().baseDir().getAbsolutePath(), + exclusions + ); for (var inputFile : inputFiles) { if (context.isCancelled()) { throw new CancellationException( diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/filter/PathAssessor.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/filter/PathAssessor.java index 928761b8da9..141b0babd9c 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/filter/PathAssessor.java +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/filter/PathAssessor.java @@ -19,15 +19,13 @@ */ package org.sonar.plugins.javascript.filter; -import static java.util.Arrays.stream; -import static java.util.stream.Stream.concat; - import org.sonar.api.batch.fs.InputFile; import org.sonar.api.config.Configuration; import org.sonar.api.utils.WildcardPattern; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.plugins.javascript.JavaScriptPlugin; +import org.sonar.plugins.javascript.utils.Exclusions; class PathAssessor implements Assessor { @@ -35,26 +33,7 @@ class PathAssessor implements Assessor { private final WildcardPattern[] excludedPatterns; PathAssessor(Configuration configuration) { - if (!isExclusionOverridden(configuration)) { - excludedPatterns = WildcardPattern.create(JavaScriptPlugin.EXCLUSIONS_DEFAULT_VALUE); - } else { - WildcardPattern[] jsExcludedPatterns = WildcardPattern.create( - configuration.getStringArray(JavaScriptPlugin.JS_EXCLUSIONS_KEY) - ); - WildcardPattern[] tsExcludedPatterns = WildcardPattern.create( - configuration.getStringArray(JavaScriptPlugin.TS_EXCLUSIONS_KEY) - ); - excludedPatterns = - concat(stream(jsExcludedPatterns), stream(tsExcludedPatterns)) - .toArray(WildcardPattern[]::new); - } - } - - private static boolean isExclusionOverridden(Configuration configuration) { - return ( - configuration.get(JavaScriptPlugin.JS_EXCLUSIONS_KEY).isPresent() || - configuration.get(JavaScriptPlugin.TS_EXCLUSIONS_KEY).isPresent() - ); + excludedPatterns = WildcardPattern.create(Exclusions.getExcludedPaths(configuration)); } @Override diff --git a/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/utils/Exclusions.java b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/utils/Exclusions.java new file mode 100644 index 00000000000..a657cbeef9f --- /dev/null +++ b/sonar-plugin/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/utils/Exclusions.java @@ -0,0 +1,33 @@ +package org.sonar.plugins.javascript.utils; + +import static java.util.Arrays.stream; +import static java.util.stream.Stream.concat; + +import org.sonar.api.config.Configuration; +import org.sonar.plugins.javascript.JavaScriptPlugin; + +public class Exclusions { + + private Exclusions() { + throw new IllegalStateException("Utility class"); + } + + public static String[] getExcludedPaths(Configuration configuration) { + if (isExclusionOverridden(configuration)) { + return concat( + stream(configuration.getStringArray(JavaScriptPlugin.JS_EXCLUSIONS_KEY)), + stream(configuration.getStringArray(JavaScriptPlugin.TS_EXCLUSIONS_KEY)) + ) + .filter(x -> !x.isBlank()) + .toArray(String[]::new); + } + return JavaScriptPlugin.EXCLUSIONS_DEFAULT_VALUE; + } + + private static boolean isExclusionOverridden(Configuration configuration) { + return ( + configuration.get(JavaScriptPlugin.JS_EXCLUSIONS_KEY).isPresent() || + configuration.get(JavaScriptPlugin.TS_EXCLUSIONS_KEY).isPresent() + ); + } +} diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java index b6a11826466..31196a02c55 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/BridgeServerImplTest.java @@ -215,12 +215,14 @@ void test_init() throws Exception { rules, Collections.emptyList(), Collections.emptyList(), - AnalysisMode.DEFAULT + AnalysisMode.DEFAULT, + "", + Collections.emptyList() ); bridgeServer.stop(); assertThat(logTester.logs()) .contains( - "{\"linterId\":\"default\",\"rules\":[{\"key\":\"key\",\"fileTypeTarget\":[\"MAIN\"],\"configurations\":[\"config\"],\"language\":\"js\"}],\"environments\":[],\"globals\":[]}" + "{\"linterId\":\"default\",\"rules\":[{\"key\":\"key\",\"fileTypeTarget\":[\"MAIN\"],\"configurations\":[\"config\"],\"language\":\"js\"}],\"environments\":[],\"globals\":[],\"baseDir\":\"\",\"exclusions\":[]}" ); } diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/HtmlSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/HtmlSensorTest.java index 1ceb4d9a85d..4cda1a9df94 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/HtmlSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/HtmlSensorTest.java @@ -59,7 +59,6 @@ import org.sonar.api.measures.FileLinesContext; import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.api.rule.RuleKey; -import org.sonar.api.testfixtures.log.LogAndArguments; import org.sonar.api.testfixtures.log.LogTesterJUnit5; import org.sonar.api.utils.log.LoggerLevel; import org.sonar.javascript.checks.CheckList; @@ -142,7 +141,7 @@ void should_create_issues() throws Exception { DefaultInputFile inputFile = createInputFile(context); sensor.execute(context); - verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any()); + verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any(), any(), any()); assertThat(context.allIssues()).hasSize(2); Iterator issues = context.allIssues().iterator(); diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java index 6e9a2fc2cc0..9316b0fc6cf 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JavaScriptEslintBasedSensorTest.java @@ -179,7 +179,7 @@ void should_create_issues() throws Exception { DefaultInputFile inputFile = createInputFile(context); sensor.execute(context); - verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any()); + verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any(), any(), any()); assertThat(context.allIssues()).hasSize(3); Iterator issues = context.allIssues().iterator(); diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java index 3bfa7595f1c..48e18cad4b3 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/JsTsSensorTest.java @@ -181,7 +181,7 @@ void should_analyse() throws Exception { createTsConfigFile(); sensor.execute(context); - verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any()); + verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any(), any(), any()); assertThat(context.allIssues()).hasSize(expectedResponse.issues.size()); assertThat(logTester.logs(LoggerLevel.DEBUG)) .contains( diff --git a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/YamlSensorTest.java b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/YamlSensorTest.java index a18fa39bff9..c49b911c6b8 100644 --- a/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/YamlSensorTest.java +++ b/sonar-plugin/sonar-javascript-plugin/src/test/java/org/sonar/plugins/javascript/bridge/YamlSensorTest.java @@ -141,7 +141,7 @@ void should_create_issues() throws Exception { DefaultInputFile inputFile = createInputFile(context); sensor.execute(context); - verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any()); + verify(bridgeServerMock, times(1)).initLinter(any(), any(), any(), any(), any(), any()); assertThat(context.allIssues()).hasSize(2); Iterator issues = context.allIssues().iterator();