From 443abea7d7e0a99c5b8abcc73bbe1d64b1dc689d Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Thu, 12 Mar 2020 13:31:01 -0700 Subject: [PATCH] chore: Introduce eslint Adds eslint support and fixes linting problems in a few files. This change adds an npm task, but does not enforce linting for builds. The idea is to slowly fix linting problems over time. Closes #238. --- .vscode/settings.json | 12 +- .vscode/tasks.json | 11 +- common/config/rush/pnpm-lock.yaml | 562 +++++++++++++++++- extensions/ql-vscode/.eslintrc.js | 37 ++ extensions/ql-vscode/package.json | 8 +- extensions/ql-vscode/src/bqrs-cli-types.ts | 68 +-- extensions/ql-vscode/src/cli.ts | 43 +- extensions/ql-vscode/src/interface.ts | 382 ++++++++---- extensions/ql-vscode/src/view/.eslintrc.js | 8 + .../ql-vscode/src/view/raw-results-table.tsx | 4 +- .../ql-vscode/src/view/result-table-utils.tsx | 4 +- .../ql-vscode/src/view/result-tables.tsx | 2 +- extensions/ql-vscode/src/view/results.tsx | 20 +- .../ql-vscode/src/vscode-tests/.eslintrc.js | 5 + extensions/ql-vscode/test/.eslintrc.js | 5 + extensions/ql-vscode/tsconfig.json | 2 +- 16 files changed, 980 insertions(+), 193 deletions(-) create mode 100644 extensions/ql-vscode/.eslintrc.js create mode 100644 extensions/ql-vscode/src/view/.eslintrc.js create mode 100644 extensions/ql-vscode/src/vscode-tests/.eslintrc.js create mode 100644 extensions/ql-vscode/test/.eslintrc.js diff --git a/.vscode/settings.json b/.vscode/settings.json index 087f0bd89..25616f6ea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,5 +22,15 @@ "common/temp": true, "**/.vscode-test": true }, - "typescript.tsdk": "./common/temp/node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version + "typescript.tsdk": "./common/temp/node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "typescriptreact" + ], + "eslint.options": { + // This is necessary so that eslint can properly resolve its plugins + "resolvePluginsRelativeTo": "./extensions/ql-vscode" + } } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 871c6c5dc..5c4c141ce 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -28,7 +28,7 @@ "file": 1, "location": 2, "message": 3 - }, + } }, "$ts-webpack" ] @@ -100,6 +100,15 @@ "clear": true }, "problemMatcher": [] + }, + { + "type": "npm", + "script": "watch", + "path": "extensions/ql-vscode/", + "problemMatcher": [ + "$gulp-tsc" + ], + "group": "build" } ] } \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 39bf68c09..4fab86f71 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -31,11 +31,14 @@ dependencies: '@types/vscode': 1.42.0 '@types/webpack': 4.41.7 '@types/xml2js': 0.4.5 + '@typescript-eslint/eslint-plugin': 2.23.0_2510d86781fe783b47b58303c18a0d9b + '@typescript-eslint/parser': 2.23.0_eslint@6.8.0+typescript@3.8.3 ansi-colors: 4.1.1 chai: 4.2.0 child-process-promise: 2.2.1 classnames: 2.2.6 css-loader: 3.1.0_webpack@4.42.0 + eslint: 6.8.0 fs-extra: 8.1.0 glob: 7.1.6 glob-promise: 3.4.0_glob@7.1.6 @@ -333,6 +336,14 @@ packages: dev: false resolution: integrity: sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ== + /@types/color-name/1.1.1: + dev: false + resolution: + integrity: sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + /@types/eslint-visitor-keys/1.0.0: + dev: false + resolution: + integrity: sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== /@types/events/3.0.0: dev: false resolution: @@ -388,6 +399,10 @@ packages: dev: false resolution: integrity: sha512-0CFu/g4mDSNkodVwWijdlr8jH7RoplRWNgovjFLEZeT+QEbbZXjBmCe3HwaWheAlCbHwomTwzZoSedeOycABug== + /@types/json-schema/7.0.4: + dev: false + resolution: + integrity: sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== /@types/jszip/3.1.7: dependencies: '@types/node': 12.12.29 @@ -534,6 +549,81 @@ packages: dev: false resolution: integrity: sha1-LrHQCl5Ow/pYx2r94S4YK2bcXBw= + /@typescript-eslint/eslint-plugin/2.23.0_2510d86781fe783b47b58303c18a0d9b: + dependencies: + '@typescript-eslint/experimental-utils': 2.23.0_eslint@6.8.0+typescript@3.8.3 + '@typescript-eslint/parser': 2.23.0_eslint@6.8.0+typescript@3.8.3 + eslint: 6.8.0 + eslint-utils: 1.4.3 + functional-red-black-tree: 1.0.1 + regexpp: 3.0.0 + tsutils: 3.17.1_typescript@3.8.3 + typescript: 3.8.3 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + '@typescript-eslint/parser': ^2.0.0 + eslint: ^5.0.0 || ^6.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + resolution: + integrity: sha512-8iA4FvRsz8qTjR0L/nK9RcRUN3QtIHQiOm69FzV7WS3SE+7P7DyGGwh3k4UNR2JBbk+Ej2Io+jLAaqKibNhmtw== + /@typescript-eslint/experimental-utils/2.23.0_eslint@6.8.0+typescript@3.8.3: + dependencies: + '@types/json-schema': 7.0.4 + '@typescript-eslint/typescript-estree': 2.23.0_typescript@3.8.3 + eslint: 6.8.0 + eslint-scope: 5.0.0 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + eslint: '*' + typescript: '*' + resolution: + integrity: sha512-OswxY59RcXH3NNPmq+4Kis2CYZPurRU6mG5xPcn24CjFyfdVli5mySwZz/g/xDbJXgDsYqNGq7enV0IziWGXVQ== + /@typescript-eslint/parser/2.23.0_eslint@6.8.0+typescript@3.8.3: + dependencies: + '@types/eslint-visitor-keys': 1.0.0 + '@typescript-eslint/experimental-utils': 2.23.0_eslint@6.8.0+typescript@3.8.3 + '@typescript-eslint/typescript-estree': 2.23.0_typescript@3.8.3 + eslint: 6.8.0 + eslint-visitor-keys: 1.1.0 + typescript: 3.8.3 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + resolution: + integrity: sha512-k61pn/Nepk43qa1oLMiyqApC6x5eP5ddPz6VUYXCAuXxbmRLqkPYzkFRKl42ltxzB2luvejlVncrEpflgQoSUg== + /@typescript-eslint/typescript-estree/2.23.0_typescript@3.8.3: + dependencies: + debug: 4.1.1 + eslint-visitor-keys: 1.1.0 + glob: 7.1.6 + is-glob: 4.0.1 + lodash: 4.17.15 + semver: 6.3.0 + tsutils: 3.17.1_typescript@3.8.3 + typescript: 3.8.3 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + resolution: + integrity: sha512-pmf7IlmvXdlEXvE/JWNNJpEvwBV59wtJqA8MLAxMKLXNKVRC3HZBXR/SlZLPWTCcwOSg9IM7GeRSV3SIerGVqw== /@webassemblyjs/ast/1.8.5: dependencies: '@webassemblyjs/helper-module-context': 1.8.5 @@ -683,6 +773,14 @@ packages: node: '>=8.15' resolution: integrity: sha512-nlAQt6YjG1VwmxhNwvXOcgxPFJR6yF6u9kbAU2uWjfeDDkBavzUC6F210+Xfb44Ui7eY3vFK6CvSr3MNKedjOw== + /acorn-jsx/5.2.0_acorn@7.1.1: + dependencies: + acorn: 7.1.1 + dev: false + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 + resolution: + integrity: sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== /acorn/5.7.4: dev: false engines: @@ -697,6 +795,13 @@ packages: hasBin: true resolution: integrity: sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + /acorn/7.1.1: + dev: false + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== /agent-base/4.3.0: dependencies: es6-promisify: 5.0.0 @@ -762,6 +867,14 @@ packages: node: '>=4' resolution: integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + /ansi-escapes/4.3.1: + dependencies: + type-fest: 0.11.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== /ansi-gray/0.1.1: dependencies: ansi-wrap: 0.1.0 @@ -788,6 +901,12 @@ packages: node: '>=6' resolution: integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + /ansi-regex/5.0.0: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== /ansi-styles/3.2.1: dependencies: color-convert: 1.9.3 @@ -796,6 +915,15 @@ packages: node: '>=4' resolution: integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + /ansi-styles/4.2.1: + dependencies: + '@types/color-name': 1.1.1 + color-convert: 2.0.1 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== /ansi-wrap/0.1.0: dev: false engines: @@ -947,6 +1075,12 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + /astral-regex/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== /async-done/1.3.2: dependencies: end-of-stream: 1.4.4 @@ -1255,6 +1389,12 @@ packages: node: '>=0.10.0' resolution: integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + /callsites/3.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== /camelcase/3.0.0: dev: false engines: @@ -1296,6 +1436,15 @@ packages: node: '>=4' resolution: integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + /chalk/3.0.0: + dependencies: + ansi-styles: 4.2.1 + supports-color: 7.1.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== /chardet/0.7.0: dev: false resolution: @@ -1385,6 +1534,14 @@ packages: node: '>=4' resolution: integrity: sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + /cli-cursor/3.1.0: + dependencies: + restore-cursor: 3.1.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== /cli-table/0.3.1: dependencies: colors: 1.0.3 @@ -1468,10 +1625,22 @@ packages: dev: false resolution: integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + /color-convert/2.0.1: + dependencies: + color-name: 1.1.4 + dev: false + engines: + node: '>=7.0.0' + resolution: + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== /color-name/1.1.3: dev: false resolution: integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + /color-name/1.1.4: + dev: false + resolution: + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== /color-support/1.1.3: dev: false hasBin: true @@ -1725,6 +1894,12 @@ packages: dev: false resolution: integrity: sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + /debug/4.1.1: + dependencies: + ms: 2.1.1 + dev: false + resolution: + integrity: sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== /debuglog/1.0.1: dev: false resolution: @@ -1749,6 +1924,10 @@ packages: node: '>=0.12' resolution: integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + /deep-is/0.1.3: + dev: false + resolution: + integrity: sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= /default-compare/1.0.0: dependencies: kind-of: 5.1.0 @@ -1862,6 +2041,14 @@ packages: dev: false resolution: integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + /doctrine/3.0.0: + dependencies: + esutils: 2.0.3 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== /dom-serializer/0.1.1: dependencies: domelementtype: 1.3.1 @@ -1959,6 +2146,10 @@ packages: dev: false resolution: integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + /emoji-regex/8.0.0: + dev: false + resolution: + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== /emojis-list/2.1.0: dev: false engines: @@ -2103,6 +2294,84 @@ packages: node: '>=4.0.0' resolution: integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + /eslint-scope/5.0.0: + dependencies: + esrecurse: 4.2.1 + estraverse: 4.3.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + /eslint-utils/1.4.3: + dependencies: + eslint-visitor-keys: 1.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + /eslint-visitor-keys/1.1.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + /eslint/6.8.0: + dependencies: + '@babel/code-frame': 7.8.3 + ajv: 6.12.0 + chalk: 2.4.2 + cross-spawn: 6.0.5 + debug: 4.1.1 + doctrine: 3.0.0 + eslint-scope: 5.0.0 + eslint-utils: 1.4.3 + eslint-visitor-keys: 1.1.0 + espree: 6.2.1 + esquery: 1.1.0 + esutils: 2.0.3 + file-entry-cache: 5.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.0 + globals: 12.4.0 + ignore: 4.0.6 + import-fresh: 3.2.1 + imurmurhash: 0.1.4 + inquirer: 7.1.0 + is-glob: 4.0.1 + js-yaml: 3.13.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.3.0 + lodash: 4.17.15 + minimatch: 3.0.4 + mkdirp: 0.5.1 + natural-compare: 1.4.0 + optionator: 0.8.3 + progress: 2.0.3 + regexpp: 2.0.1 + semver: 6.3.0 + strip-ansi: 5.2.0 + strip-json-comments: 3.0.1 + table: 5.4.6 + text-table: 0.2.0 + v8-compile-cache: 2.0.3 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + hasBin: true + resolution: + integrity: sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== + /espree/6.2.1: + dependencies: + acorn: 7.1.1 + acorn-jsx: 5.2.0_acorn@7.1.1 + eslint-visitor-keys: 1.1.0 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== /esprima/4.0.1: dev: false engines: @@ -2110,6 +2379,14 @@ packages: hasBin: true resolution: integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + /esquery/1.1.0: + dependencies: + estraverse: 4.3.0 + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q== /esrecurse/4.2.1: dependencies: estraverse: 4.3.0 @@ -2257,6 +2534,10 @@ packages: dev: false resolution: integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + /fast-levenshtein/2.0.6: + dev: false + resolution: + integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= /fd-slicer/1.1.0: dependencies: pend: 1.2.0 @@ -2275,6 +2556,22 @@ packages: node: '>=4' resolution: integrity: sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + /figures/3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + /file-entry-cache/5.0.1: + dependencies: + flat-cache: 2.0.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== /file-uri-to-path/1.0.0: dev: false optional: true @@ -2358,6 +2655,16 @@ packages: node: '>= 0.10' resolution: integrity: sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== + /flat-cache/2.0.1: + dependencies: + flatted: 2.0.1 + rimraf: 2.6.3 + write: 1.0.3 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== /flat/4.1.0: dependencies: is-buffer: 2.0.4 @@ -2365,6 +2672,10 @@ packages: hasBin: true resolution: integrity: sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + /flatted/2.0.1: + dev: false + resolution: + integrity: sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== /flush-write-stream/1.1.1: dependencies: inherits: 2.0.4 @@ -2489,6 +2800,10 @@ packages: dev: false resolution: integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + /functional-red-black-tree/1.0.1: + dev: false + resolution: + integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= /get-caller-file/1.0.3: dev: false resolution: @@ -2536,6 +2851,14 @@ packages: dev: false resolution: integrity: sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + /glob-parent/5.1.0: + dependencies: + is-glob: 4.0.1 + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== /glob-promise/3.4.0_glob@7.1.6: dependencies: '@types/glob': 7.1.1 @@ -2650,6 +2973,14 @@ packages: node: '>=6' resolution: integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + /globals/12.4.0: + dependencies: + type-fest: 0.8.1 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== /glogg/1.0.2: dependencies: sparkles: 1.0.1 @@ -2917,6 +3248,21 @@ packages: dev: false resolution: integrity: sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + /ignore/4.0.6: + dev: false + engines: + node: '>= 4' + resolution: + integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + /import-fresh/3.2.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== /import-local/2.0.0: dependencies: pkg-dir: 3.0.0 @@ -2984,6 +3330,26 @@ packages: node: '>=6.0.0' resolution: integrity: sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== + /inquirer/7.1.0: + dependencies: + ansi-escapes: 4.3.1 + chalk: 3.0.0 + cli-cursor: 3.1.0 + cli-width: 2.2.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.15 + mute-stream: 0.0.8 + run-async: 2.4.0 + rxjs: 6.5.4 + string-width: 4.2.0 + strip-ansi: 6.0.0 + through: 2.3.8 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== /interpret/1.2.0: dev: false engines: @@ -3131,6 +3497,12 @@ packages: node: '>=4' resolution: integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + /is-fullwidth-code-point/3.0.0: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== /is-glob/3.1.0: dependencies: is-extglob: 2.1.1 @@ -3414,6 +3786,15 @@ packages: dev: false resolution: integrity: sha1-Mr7p+tFoMo1q6oUi2DP0GA7tHaM= + /levn/0.3.0: + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= /liftoff/3.1.0: dependencies: extend: 3.0.2 @@ -3911,6 +4292,10 @@ packages: node: '>=0.10.0' resolution: integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + /natural-compare/1.4.0: + dev: false + resolution: + integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= /neo-async/2.6.1: dev: false resolution: @@ -4190,6 +4575,27 @@ packages: node: '>=4' resolution: integrity: sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + /onetime/5.1.0: + dependencies: + mimic-fn: 2.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + /optionator/0.8.3: + dependencies: + deep-is: 0.1.3 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.3 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== /ordered-read-streams/1.0.1: dependencies: readable-stream: 2.3.7 @@ -4322,6 +4728,14 @@ packages: dev: false resolution: integrity: sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + /parent-module/1.0.1: + dependencies: + callsites: 3.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== /parse-asn1/5.1.5: dependencies: asn1.js: 4.10.1 @@ -4620,6 +5034,12 @@ packages: node: '>=6.0.0' resolution: integrity: sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== + /prelude-ls/1.1.2: + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= /pretty-hrtime/1.0.3: dev: false engines: @@ -4636,6 +5056,12 @@ packages: node: '>= 0.6.0' resolution: integrity: sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + /progress/2.0.3: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== /promise-inflight/1.0.1: dev: false resolution: @@ -4893,6 +5319,18 @@ packages: node: '>=0.10.0' resolution: integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + /regexpp/2.0.1: + dev: false + engines: + node: '>=6.5.0' + resolution: + integrity: sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + /regexpp/3.0.0: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g== /remove-bom-buffer/3.0.0: dependencies: is-buffer: 1.1.6 @@ -4981,6 +5419,12 @@ packages: node: '>=4' resolution: integrity: sha1-six699nWiBvItuZTM17rywoYh0g= + /resolve-from/4.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== /resolve-options/1.1.0: dependencies: value-or-function: 3.0.0 @@ -5008,12 +5452,28 @@ packages: node: '>=4' resolution: integrity: sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + /restore-cursor/3.1.0: + dependencies: + onetime: 5.1.0 + signal-exit: 3.0.2 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== /ret/0.1.15: dev: false engines: node: '>=0.12' resolution: integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + /rimraf/2.6.3: + dependencies: + glob: 7.1.6 + dev: false + hasBin: true + resolution: + integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== /rimraf/2.7.1: dependencies: glob: 7.1.6 @@ -5186,6 +5646,16 @@ packages: dev: false resolution: integrity: sha512-c4bREcvuK5VuEGyMW/Oim9I3Rq49Vzb0aMdxouFaA44QCFpilc5LJOugrX+mkrvikbqCimxuK+4cnHVNnLR41g== + /slice-ansi/2.1.0: + dependencies: + ansi-styles: 3.2.1 + astral-regex: 1.0.0 + is-fullwidth-code-point: 2.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== /snapdragon-node/2.1.1: dependencies: define-property: 1.0.0 @@ -5404,6 +5874,16 @@ packages: node: '>=6' resolution: integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + /string-width/4.2.0: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== /string.prototype.padend/3.1.0: dependencies: define-properties: 1.1.3 @@ -5467,6 +5947,14 @@ packages: node: '>=6' resolution: integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + /strip-ansi/6.0.0: + dependencies: + ansi-regex: 5.0.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== /strip-bom-string/1.0.0: dev: false engines: @@ -5505,6 +5993,12 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo= + /strip-json-comments/3.0.1: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== /style-loader/0.23.1: dependencies: loader-utils: 1.4.0 @@ -5553,6 +6047,17 @@ packages: dev: false resolution: integrity: sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= + /table/5.4.6: + dependencies: + ajv: 6.12.0 + lodash: 4.17.15 + slice-ansi: 2.1.0 + string-width: 3.1.0 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== /tapable/1.1.3: dev: false engines: @@ -5603,6 +6108,10 @@ packages: hasBin: true resolution: integrity: sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g== + /text-table/0.2.0: + dev: false + resolution: + integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= /thenify-all/1.6.0: dependencies: thenify: 3.3.0 @@ -5792,6 +6301,17 @@ packages: dev: false resolution: integrity: sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + /tsutils/3.17.1_typescript@3.8.3: + dependencies: + tslib: 1.11.1 + typescript: 3.8.3 + dev: false + engines: + node: '>= 6' + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + resolution: + integrity: sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== /tty-browserify/0.0.0: dev: false resolution: @@ -5802,12 +6322,32 @@ packages: node: '>=0.6.11 <=0.7.0 || >=0.7.3' resolution: integrity: sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM= + /type-check/0.3.2: + dependencies: + prelude-ls: 1.1.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= /type-detect/4.0.8: dev: false engines: node: '>=4' resolution: integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + /type-fest/0.11.0: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== + /type-fest/0.8.1: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== /type/1.2.0: dev: false resolution: @@ -6258,6 +6798,12 @@ packages: dev: false resolution: integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + /word-wrap/1.2.3: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== /wordwrap/1.0.0: dev: false resolution: @@ -6335,6 +6881,14 @@ packages: node: '>=8.15' resolution: integrity: sha512-OHzbrlgjw/K/BAH6LdEOcSQFz5nkk0I/25CjKLIVFvcg2Ej7+QE/GTnitgqWnhlsdghor7OV5gfttQPGogQ1XA== + /write/1.0.3: + dependencies: + mkdirp: 0.5.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== /xtend/4.0.2: dev: false engines: @@ -6580,10 +7134,13 @@ packages: '@types/vscode': 1.42.0 '@types/webpack': 4.41.7 '@types/xml2js': 0.4.5 + '@typescript-eslint/eslint-plugin': 2.23.0_2510d86781fe783b47b58303c18a0d9b + '@typescript-eslint/parser': 2.23.0_eslint@6.8.0+typescript@3.8.3 chai: 4.2.0 child-process-promise: 2.2.1 classnames: 2.2.6 css-loader: 3.1.0_webpack@4.42.0 + eslint: 6.8.0 fs-extra: 8.1.0 glob: 7.1.6 glob-promise: 3.4.0_glob@7.1.6 @@ -6619,7 +7176,7 @@ packages: dev: false name: '@rush-temp/vscode-codeql' resolution: - integrity: sha512-NHC4bvR4wb9iYerRor2EFewpW85pZ5sKXAuJ47VGnP3bNTrstzILDPOPGjshp7Tom952O7iw0gzw5Ow7DgxYGQ== + integrity: sha512-S/tOZMV3yl8jqavEC2X5ly4pwsb8hcACsAfEggZ5x/l7HDplczVae+Xtc49JFeMueYF00KZN1dSM0cADeftzew== tarball: 'file:projects/vscode-codeql.tgz' version: 0.0.0 registry: '' @@ -6656,11 +7213,14 @@ specifiers: '@types/vscode': ^1.39.0 '@types/webpack': ^4.32.1 '@types/xml2js': ~0.4.4 + '@typescript-eslint/eslint-plugin': ~2.23.0 + '@typescript-eslint/parser': ~2.23.0 ansi-colors: ^4.0.1 chai: ^4.2.0 child-process-promise: ^2.2.1 classnames: ~2.2.6 css-loader: ~3.1.0 + eslint: ~6.8.0 fs-extra: ^8.1.0 glob: ^7.1.4 glob-promise: ^3.4.0 diff --git a/extensions/ql-vscode/.eslintrc.js b/extensions/ql-vscode/.eslintrc.js new file mode 100644 index 000000000..1cc4c0d18 --- /dev/null +++ b/extensions/ql-vscode/.eslintrc.js @@ -0,0 +1,37 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + ecmaFeatures: { + modules: true, + }, + }, + plugins: ['@typescript-eslint'], + env: { + node: true, + es6: true + }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + ], + rules: { + '@typescript-eslint/no-use-before-define': 0, + '@typescript-eslint/no-unused-vars': ["warn", { + "vars": "all", + "args": "none", + "ignoreRestSiblings": false + }], + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-explicit-any": "off", + "prefer-const": ["warn", {"destructuring": "all"}], + "indent": "off", + "@typescript-eslint/indent": ["error", 2, { + "SwitchCase": 1, + "FunctionDeclaration": { "body": 1, "parameters": 1 } + }], + "@typescript-eslint/no-throw-literal": "error" + }, +}; diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index 5c37abaa3..823e5f363 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -375,7 +375,8 @@ "integration": "node ./out/vscode-tests/run-integration-tests.js", "update-vscode": "node ./node_modules/vscode/bin/install", "postinstall": "node ./node_modules/vscode/bin/install", - "format": "tsfmt -r" + "format": "tsfmt -r", + "lint": "eslint . --ext .ts,.tsx" }, "dependencies": { "child-process-promise": "^2.2.1", @@ -440,6 +441,9 @@ "vsce": "^1.65.0", "vscode-test": "^1.0.0", "webpack": "^4.38.0", - "webpack-cli": "^3.3.2" + "webpack-cli": "^3.3.2", + "eslint": "~6.8.0", + "@typescript-eslint/eslint-plugin": "~2.23.0", + "@typescript-eslint/parser": "~2.23.0" } } diff --git a/extensions/ql-vscode/src/bqrs-cli-types.ts b/extensions/ql-vscode/src/bqrs-cli-types.ts index f7827a26e..397937ca0 100644 --- a/extensions/ql-vscode/src/bqrs-cli-types.ts +++ b/extensions/ql-vscode/src/bqrs-cli-types.ts @@ -4,16 +4,16 @@ export const PAGE_SIZE = 1000; export type ColumnKind = "f" | "i" | "s" | "b" | "d" | "e"; export interface Column { - name?: string, - kind: ColumnKind, + name?: string; + kind: ColumnKind; } export interface ResultSetSchema { - name: string, - rows: number, - columns: Column[], - pagination?: PaginationInfo, + name: string; + rows: number; + columns: Column[]; + pagination?: PaginationInfo; } export function getResultSetSchema(resultSetName: string, resultSets: BQRSInfo): ResultSetSchema | undefined { @@ -25,47 +25,47 @@ export function getResultSetSchema(resultSetName: string, resultSets: BQRSInfo): return undefined; } export interface PaginationInfo { - "step-size": number, - offsets: number[], + "step-size": number; + offsets: number[]; } export interface BQRSInfo { - "result-sets": ResultSetSchema[] + "result-sets": ResultSetSchema[]; } export interface EntityValue { - url?: UrlValue, - label?: string + url?: UrlValue; + label?: string; } export interface LineColumnLocation { - uri: string - startLine: number, - startColumn: number, - endLine: number, - endColumn: number, - charOffset: never - charLength: never + uri: string; + startLine: number; + startColumn: number; + endLine: number; + endColumn: number; + charOffset: never; + charLength: never; } export interface OffsetLengthLocation { - uri: string, - startLine: never, - startColumn: never, - endLine: never, - endColumn: never, - charOffset: number, - charLength: number, + uri: string; + startLine: never; + startColumn: never; + endLine: never; + endColumn: never; + charOffset: number; + charLength: number; } export interface WholeFileLocation { - uri: string, - startLine: never, - startColumn: never, - endLine: never, - endColumn: never, - charOffset: never, - charLength: never, + uri: string; + startLine: never; + startColumn: never; + endLine: never; + endColumn: never; + charOffset: never; + charLength: never; } export type UrlValue = LineColumnLocation | OffsetLengthLocation | WholeFileLocation | string; @@ -74,6 +74,6 @@ export type UrlValue = LineColumnLocation | OffsetLengthLocation | WholeFileLoca export type ColumnValue = EntityValue | number | string | boolean; export interface DecodedBqrsChunk { - tuples: ColumnValue[][], - next?: number + tuples: ColumnValue[][]; + next?: number; } diff --git a/extensions/ql-vscode/src/cli.ts b/extensions/ql-vscode/src/cli.ts index b07da4c8a..ca0f6cb57 100644 --- a/extensions/ql-vscode/src/cli.ts +++ b/extensions/ql-vscode/src/cli.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/camelcase */ import * as cpp from 'child-process-promise'; import * as child_process from 'child_process'; import * as fs from 'fs-extra'; @@ -28,10 +29,10 @@ const LOGGING_FLAGS = ['-v', '--log-to-stderr']; * The expected output of `codeql resolve library-path`. */ export interface QuerySetup { - libraryPath: string[], - dbscheme: string, - relativeName?: string, - compilationCache?: string + libraryPath: string[]; + dbscheme: string; + relativeName?: string; + compilationCache?: string; } /** @@ -121,11 +122,11 @@ export class CodeQLCliServer implements Disposable { } - dispose() { + dispose(): void { this.killProcessIfRunning(); } - killProcessIfRunning() { + killProcessIfRunning(): void { if (this.process) { // Tell the Java CLI server process to shut down. this.logger.log('Sending shutdown request'); @@ -152,8 +153,8 @@ export class CodeQLCliServer implements Disposable { /** * Restart the server when the current command terminates */ - private restartCliServer() { - let callback = () => { + private restartCliServer(): void { + const callback = (): void => { try { this.killProcessIfRunning(); } finally { @@ -187,11 +188,11 @@ export class CodeQLCliServer implements Disposable { */ private async launchProcess(): Promise { const config = await this.getCodeQlPath(); - return spawnServer(config, "CodeQL CLI Server", ["execute", "cli-server"], [], this.logger, _data => { }) + return spawnServer(config, "CodeQL CLI Server", ["execute", "cli-server"], [], this.logger, _data => { /**/ }) } private async runCodeQlCliInternal(command: string[], commandArgs: string[], description: string): Promise { - let stderrBuffers: Buffer[] = []; + const stderrBuffers: Buffer[] = []; if (this.commandInProcess) { throw new Error("runCodeQlCliInternal called while cli was running") } @@ -204,7 +205,7 @@ export class CodeQLCliServer implements Disposable { // Grab the process so that typescript know that it is always defined. const process = this.process; // The array of fragments of stdout - let stdoutBuffers: Buffer[] = []; + const stdoutBuffers: Buffer[] = []; // Compute the full args array const args = command.concat(LOGGING_FLAGS).concat(commandArgs); @@ -233,9 +234,9 @@ export class CodeQLCliServer implements Disposable { process.stdin.write(this.nullBuffer) }); // Join all the data together - let fullBuffer = Buffer.concat(stdoutBuffers); + const fullBuffer = Buffer.concat(stdoutBuffers); // Make sure we remove the terminator; - let data = fullBuffer.toString("utf8", 0, fullBuffer.length - 1); + const data = fullBuffer.toString("utf8", 0, fullBuffer.length - 1); this.logger.log(`CLI command succeeded.`); return data; } catch (err) { @@ -264,7 +265,7 @@ export class CodeQLCliServer implements Disposable { /** * Run the next command in the queue */ - private runNext() { + private runNext(): void { const callback = this.commandQueue.shift(); if (callback) { callback(); @@ -367,7 +368,7 @@ export class CodeQLCliServer implements Disposable { return new Promise((resolve, reject) => { // Construct the command that actually does the work - const callback = () => { + const callback = (): void => { try { this.runCodeQlCliInternal(command, commandArgs, description).then(resolve, reject); } catch (err) { @@ -435,8 +436,9 @@ export class CodeQLCliServer implements Disposable { * @param workspaces Workspace paths to use as search paths for QL packs. * @param options Additional options. */ - public async* runTests(testPaths: string[], workspaces: string[], options: TestRunOptions): - AsyncGenerator { + public async* runTests( + testPaths: string[], workspaces: string[], options: TestRunOptions + ): AsyncGenerator { const subcommandArgs = [ '--additional-packs', workspaces.join(path.delimiter), @@ -507,7 +509,7 @@ export class CodeQLCliServer implements Disposable { } - async interpretBqrs(metadata: { kind: string, id: string }, resultsPath: string, interpretedResultsPath: string, sourceInfo?: SourceInfo): Promise { + async interpretBqrs(metadata: { kind: string; id: string }, resultsPath: string, interpretedResultsPath: string, sourceInfo?: SourceInfo): Promise { const args = [ `-t=kind=${metadata.kind}`, `-t=id=${metadata.id}`, @@ -751,8 +753,9 @@ class SplitBuffer { * @param separators The list of strings that act as line separators. * @returns A sequence of lines (not including separators). */ -async function* splitStreamAtSeparators(stream: Readable, separators: string[]): - AsyncGenerator { +async function* splitStreamAtSeparators( + stream: Readable, separators: string[] +): AsyncGenerator { const buffer = new SplitBuffer(separators); for await (const chunk of stream) { diff --git a/extensions/ql-vscode/src/interface.ts b/extensions/ql-vscode/src/interface.ts index 5d5462a7f..e76966008 100644 --- a/extensions/ql-vscode/src/interface.ts +++ b/extensions/ql-vscode/src/interface.ts @@ -42,7 +42,11 @@ export enum WebviewReveal { * Returns HTML to populate the given webview. * Uses a content security policy that only loads the given script. */ -function getHtmlForWebview(webview: vscode.Webview, scriptUriOnDisk: vscode.Uri, stylesheetUriOnDisk: vscode.Uri) { +function getHtmlForWebview( + webview: vscode.Webview, + scriptUriOnDisk: vscode.Uri, + stylesheetUriOnDisk: vscode.Uri +): void { // Convert the on-disk URIs into webview URIs. const scriptWebviewUri = webview.asWebviewUri(scriptUriOnDisk); const stylesheetWebviewUri = webview.asWebviewUri(stylesheetUriOnDisk); @@ -115,19 +119,38 @@ export class InterfaceManager extends DisposableObject { private _panelLoaded = false; private _panelLoadedCallBacks: (() => void)[] = []; - private readonly _diagnosticCollection = languages.createDiagnosticCollection(`codeql-query-results`); - - constructor(public ctx: vscode.ExtensionContext, private databaseManager: DatabaseManager, - public cliServer: CodeQLCliServer, public logger: Logger) { + private readonly _diagnosticCollection = languages.createDiagnosticCollection( + `codeql-query-results` + ); + constructor( + public ctx: vscode.ExtensionContext, + private databaseManager: DatabaseManager, + public cliServer: CodeQLCliServer, + public logger: Logger + ) { super(); this.push(this._diagnosticCollection); - this.push(vscode.window.onDidChangeTextEditorSelection(this.handleSelectionChange.bind(this))); - this.push(vscode.commands.registerCommand('codeQLQueryResults.nextPathStep', this.navigatePathStep.bind(this, 1))); - this.push(vscode.commands.registerCommand('codeQLQueryResults.previousPathStep', this.navigatePathStep.bind(this, -1))); + this.push( + vscode.window.onDidChangeTextEditorSelection( + this.handleSelectionChange.bind(this) + ) + ); + this.push( + vscode.commands.registerCommand( + "codeQLQueryResults.nextPathStep", + this.navigatePathStep.bind(this, 1) + ) + ); + this.push( + vscode.commands.registerCommand( + "codeQLQueryResults.previousPathStep", + this.navigatePathStep.bind(this, -1) + ) + ); } - navigatePathStep(direction: number) { + navigatePathStep(direction: number): void { this.postMessage({ t: "navigatePath", direction }); } @@ -136,9 +159,9 @@ export class InterfaceManager extends DisposableObject { getPanel(): vscode.WebviewPanel { if (this._panel == undefined) { const { ctx } = this; - const panel = this._panel = Window.createWebviewPanel( - 'resultsView', // internal name - 'CodeQL Query Results', // user-visible name + const panel = (this._panel = Window.createWebviewPanel( + "resultsView", // internal name + "CodeQL Query Results", // user-visible name { viewColumn: vscode.ViewColumn.Beside, preserveFocus: true }, { enableScripts: true, @@ -146,61 +169,96 @@ export class InterfaceManager extends DisposableObject { retainContextWhenHidden: true, localResourceRoots: [ vscode.Uri.file(tmpDir.name), - vscode.Uri.file(path.join(this.ctx.extensionPath, 'out')) + vscode.Uri.file(path.join(this.ctx.extensionPath, "out")) ] } + )); + this._panel.onDidDispose( + () => { + this._panel = undefined; + }, + null, + ctx.subscriptions + ); + const scriptPathOnDisk = vscode.Uri.file( + ctx.asAbsolutePath("out/resultsView.js") + ); + const stylesheetPathOnDisk = vscode.Uri.file( + ctx.asAbsolutePath("out/resultsView.css") + ); + getHtmlForWebview( + panel.webview, + scriptPathOnDisk, + stylesheetPathOnDisk + ); + panel.webview.onDidReceiveMessage( + async e => this.handleMsgFromView(e), + undefined, + ctx.subscriptions ); - this._panel.onDidDispose(() => { this._panel = undefined; }, null, ctx.subscriptions); - const scriptPathOnDisk = vscode.Uri - .file(ctx.asAbsolutePath('out/resultsView.js')); - const stylesheetPathOnDisk = vscode.Uri - .file(ctx.asAbsolutePath('out/resultsView.css')); - getHtmlForWebview(panel.webview, scriptPathOnDisk, stylesheetPathOnDisk); - panel.webview.onDidReceiveMessage(async (e) => this.handleMsgFromView(e), undefined, ctx.subscriptions); } return this._panel; } - private async changeSortState(update: (query: CompletedQuery) => Promise): Promise { + private async changeSortState( + update: (query: CompletedQuery) => Promise + ): Promise { if (this._displayedQuery === undefined) { - showAndLogErrorMessage("Failed to sort results since evaluation info was unknown."); + showAndLogErrorMessage( + "Failed to sort results since evaluation info was unknown." + ); return; } // Notify the webview that it should expect new results. - await this.postMessage({ t: 'resultsUpdating' }); + await this.postMessage({ t: "resultsUpdating" }); await update(this._displayedQuery); - await this.showResults(this._displayedQuery, WebviewReveal.NotForced, true); + await this.showResults( + this._displayedQuery, + WebviewReveal.NotForced, + true + ); } - private async handleMsgFromView(msg: FromResultsViewMsg): Promise { + private async handleMsgFromView( + msg: FromResultsViewMsg + ): Promise { switch (msg.t) { - case 'viewSourceFile': { - const databaseItem = this.databaseManager.findDatabaseItem(Uri.parse(msg.databaseUri)); + case "viewSourceFile": { + const databaseItem = this.databaseManager.findDatabaseItem( + Uri.parse(msg.databaseUri) + ); if (databaseItem !== undefined) { try { await showLocation(msg.loc, databaseItem); - } - catch (e) { + } catch (e) { if (e instanceof Error) { if (e.message.match(/File not found/)) { - vscode.window.showErrorMessage(`Original file of this result is not in the database's source archive.`); + vscode.window.showErrorMessage( + `Original file of this result is not in the database's source archive.` + ); + } else { + this.logger.log( + `Unable to handleMsgFromView: ${e.message}` + ); } - else { - this.logger.log(`Unable to handleMsgFromView: ${e.message}`); - } - } - else { + } else { this.logger.log(`Unable to handleMsgFromView: ${e}`); } } } break; } - case 'toggleDiagnostics': { + case "toggleDiagnostics": { if (msg.visible) { - const databaseItem = this.databaseManager.findDatabaseItem(Uri.parse(msg.databaseUri)); + const databaseItem = this.databaseManager.findDatabaseItem( + Uri.parse(msg.databaseUri) + ); if (databaseItem !== undefined) { - await this.showResultsAsDiagnostics(msg.origResultsPaths, msg.metadata, databaseItem); + await this.showResultsAsDiagnostics( + msg.origResultsPaths, + msg.metadata, + databaseItem + ); } } else { // TODO: Only clear diagnostics on the same database. @@ -213,11 +271,19 @@ export class InterfaceManager extends DisposableObject { this._panelLoadedCallBacks.forEach(cb => cb()); this._panelLoadedCallBacks = []; break; - case 'changeSort': - await this.changeSortState((query) => query.updateSortState(this.cliServer, msg.resultSetName, msg.sortState)); + case "changeSort": + await this.changeSortState(query => + query.updateSortState( + this.cliServer, + msg.resultSetName, + msg.sortState + ) + ); break; - case 'changeInterpretedSort': - await this.changeSortState((query) => query.updateInterpretedSortState(this.cliServer, msg.sortState)); + case "changeInterpretedSort": + await this.changeSortState(query => + query.updateInterpretedSortState(this.cliServer, msg.sortState) + ); break; default: assertNever(msg); @@ -229,34 +295,45 @@ export class InterfaceManager extends DisposableObject { } private waitForPanelLoaded(): Promise { - return new Promise((resolve, _reject) => { + return new Promise(resolve => { if (this._panelLoaded) { resolve(); } else { - this._panelLoadedCallBacks.push(resolve) + this._panelLoadedCallBacks.push(resolve); } - }) + }); } /** - * Show query results in webview panel. - * @param results Evaluation info for the executed query. - * @param shouldKeepOldResultsWhileRendering Should keep old results while rendering. - * @param forceReveal Force the webview panel to be visible and - * Appropriate when the user has just performed an explicit - * UI interaction requesting results, e.g. clicking on a query - * history entry. - */ - public async showResults(results: CompletedQuery, forceReveal: WebviewReveal, shouldKeepOldResultsWhileRendering: boolean = false): Promise { + * Show query results in webview panel. + * @param results Evaluation info for the executed query. + * @param shouldKeepOldResultsWhileRendering Should keep old results while rendering. + * @param forceReveal Force the webview panel to be visible and + * Appropriate when the user has just performed an explicit + * UI interaction requesting results, e.g. clicking on a query + * history entry. + */ + public async showResults( + results: CompletedQuery, + forceReveal: WebviewReveal, + shouldKeepOldResultsWhileRendering = false + ): Promise { if (results.result.resultType !== messages.QueryResultType.SUCCESS) { return; } - const interpretation = await this.interpretResultsInfo(results.query, results.interpretedResultsSortState); + const interpretation = await this.interpretResultsInfo( + results.query, + results.interpretedResultsSortState + ); const sortedResultsMap: SortedResultsMap = {}; - results.sortedResultsInfo.forEach((v, k) => - sortedResultsMap[k] = this.convertPathPropertiesToWebviewUris(v)); + results.sortedResultsInfo.forEach( + (v, k) => + (sortedResultsMap[k] = this.convertPathPropertiesToWebviewUris( + v + )) + ); this._displayedQuery = results; @@ -264,16 +341,17 @@ export class InterfaceManager extends DisposableObject { await this.waitForPanelLoaded(); if (forceReveal === WebviewReveal.Forced) { panel.reveal(undefined, true); - } - else if (!panel.visible) { + } else if (!panel.visible) { // The results panel exists, (`.getPanel()` guarantees it) but // is not visible; it's in a not-currently-viewed tab. Show a // more asynchronous message to not so abruptly interrupt // user's workflow by immediately revealing the panel. - const showButton = 'View Results'; + const showButton = "View Results"; const queryName = results.queryName; const resultPromise = vscode.window.showInformationMessage( - `Finished running query ${(queryName.length > 0) ? ` “${queryName}”` : ''}.`, + `Finished running query ${ + queryName.length > 0 ? ` “${queryName}”` : "" + }.`, showButton ); // Address this click asynchronously so we still update the @@ -286,10 +364,12 @@ export class InterfaceManager extends DisposableObject { } await this.postMessage({ - t: 'setState', + t: "setState", interpretation, origResultsPaths: results.query.resultsPaths, - resultsPath: this.convertPathToWebviewUri(results.query.resultsPaths.resultsPath), + resultsPath: this.convertPathToWebviewUri( + results.query.resultsPaths.resultsPath + ), sortedResultsMap, database: results.database, shouldKeepOldResultsWhileRendering, @@ -297,8 +377,19 @@ export class InterfaceManager extends DisposableObject { }); } - private async getTruncatedResults(metadata: QueryMetadata | undefined, resultsPaths: ResultsPaths, sourceInfo: cli.SourceInfo | undefined, sourceLocationPrefix: string, sortState: InterpretedResultsSortState | undefined): Promise { - const sarif = await interpretResults(this.cliServer, metadata, resultsPaths.resultsPath, sourceInfo); + private async getTruncatedResults( + metadata: QueryMetadata | undefined, + resultsPaths: ResultsPaths, + sourceInfo: cli.SourceInfo | undefined, + sourceLocationPrefix: string, + sortState: InterpretedResultsSortState | undefined + ): Promise { + const sarif = await interpretResults( + this.cliServer, + metadata, + resultsPaths.resultsPath, + sourceInfo + ); // For performance reasons, limit the number of results we try // to serialize and send to the webview. TODO: possibly also // limit number of paths per result, number of steps per path, @@ -311,68 +402,110 @@ export class InterfaceManager extends DisposableObject { if (run.results !== undefined) { sortInterpretedResults(run.results, sortState); if (run.results.length > INTERPRETED_RESULTS_PER_RUN_LIMIT) { - numTruncatedResults += run.results.length - INTERPRETED_RESULTS_PER_RUN_LIMIT; - run.results = run.results.slice(0, INTERPRETED_RESULTS_PER_RUN_LIMIT); + numTruncatedResults += + run.results.length - INTERPRETED_RESULTS_PER_RUN_LIMIT; + run.results = run.results.slice( + 0, + INTERPRETED_RESULTS_PER_RUN_LIMIT + ); } } }); - return { sarif, sourceLocationPrefix, numTruncatedResults, sortState }; + return { + sarif, + sourceLocationPrefix, + numTruncatedResults, + sortState + }; } - private async interpretResultsInfo(query: QueryInfo, sortState: InterpretedResultsSortState | undefined): Promise { + private async interpretResultsInfo( + query: QueryInfo, + sortState: InterpretedResultsSortState | undefined + ): Promise { let interpretation: Interpretation | undefined = undefined; - if (await query.hasInterpretedResults() - && query.quickEvalPosition === undefined // never do results interpretation if quickEval + if ( + (await query.hasInterpretedResults()) && + query.quickEvalPosition === undefined // never do results interpretation if quickEval ) { try { - const sourceLocationPrefix = await query.dbItem.getSourceLocationPrefix(this.cliServer); + const sourceLocationPrefix = await query.dbItem.getSourceLocationPrefix( + this.cliServer + ); const sourceArchiveUri = query.dbItem.sourceArchive; - const sourceInfo = sourceArchiveUri === undefined ? - undefined : - { sourceArchive: sourceArchiveUri.fsPath, sourceLocationPrefix }; - interpretation = await this.getTruncatedResults(query.metadata, query.resultsPaths, sourceInfo, sourceLocationPrefix, sortState); - } - catch (e) { + const sourceInfo = + sourceArchiveUri === undefined + ? undefined + : { + sourceArchive: sourceArchiveUri.fsPath, + sourceLocationPrefix + }; + interpretation = await this.getTruncatedResults( + query.metadata, + query.resultsPaths, + sourceInfo, + sourceLocationPrefix, + sortState + ); + } catch (e) { // If interpretation fails, accept the error and continue // trying to render uninterpreted results anyway. - this.logger.log(`Exception during results interpretation: ${e.message}. Will show raw results instead.`); + this.logger.log( + `Exception during results interpretation: ${e.message}. Will show raw results instead.` + ); } } return interpretation; } - - private async showResultsAsDiagnostics(resultsInfo: ResultsPaths, metadata: QueryMetadata | undefined, database: DatabaseItem) { - const sourceLocationPrefix = await database.getSourceLocationPrefix(this.cliServer); + private async showResultsAsDiagnostics( + resultsInfo: ResultsPaths, + metadata: QueryMetadata | undefined, + database: DatabaseItem + ): Promise { + const sourceLocationPrefix = await database.getSourceLocationPrefix( + this.cliServer + ); const sourceArchiveUri = database.sourceArchive; - const sourceInfo = sourceArchiveUri === undefined ? - undefined : - { sourceArchive: sourceArchiveUri.fsPath, sourceLocationPrefix }; + const sourceInfo = + sourceArchiveUri === undefined + ? undefined + : { + sourceArchive: sourceArchiveUri.fsPath, + sourceLocationPrefix + }; const interpretation = await this.getTruncatedResults( metadata, resultsInfo, sourceInfo, sourceLocationPrefix, - undefined, + undefined ); try { - await this.showProblemResultsAsDiagnostics(interpretation, database); - } - catch (e) { + await this.showProblemResultsAsDiagnostics( + interpretation, + database + ); + } catch (e) { const msg = e instanceof Error ? e.message : e.toString(); - this.logger.log(`Exception while computing problem results as diagnostics: ${msg}`); + this.logger.log( + `Exception while computing problem results as diagnostics: ${msg}` + ); this._diagnosticCollection.clear(); } - } - private async showProblemResultsAsDiagnostics(interpretation: Interpretation, databaseItem: DatabaseItem): Promise { + private async showProblemResultsAsDiagnostics( + interpretation: Interpretation, + databaseItem: DatabaseItem + ): Promise { const { sarif, sourceLocationPrefix } = interpretation; - if (!sarif.runs || !sarif.runs[0].results) { - this.logger.log("Didn't find a run in the sarif results. Error processing sarif?") + this.logger.log( + "Didn't find a run in the sarif results. Error processing sarif?" + ); return; } @@ -381,59 +514,68 @@ export class InterfaceManager extends DisposableObject { for (const result of sarif.runs[0].results) { const message = result.message.text; if (message === undefined) { - this.logger.log("Sarif had result without plaintext message") + this.logger.log("Sarif had result without plaintext message"); continue; } if (!result.locations) { - this.logger.log("Sarif had result without location") + this.logger.log("Sarif had result without location"); continue; } - const sarifLoc = parseSarifLocation(result.locations[0], sourceLocationPrefix); + const sarifLoc = parseSarifLocation( + result.locations[0], + sourceLocationPrefix + ); if (sarifLoc.t == "NoLocation") { continue; } - const resultLocation = tryResolveLocation(sarifLoc, databaseItem) + const resultLocation = tryResolveLocation(sarifLoc, databaseItem); if (!resultLocation) { - this.logger.log("Sarif location was not resolvable " + sarifLoc) + this.logger.log("Sarif location was not resolvable " + sarifLoc); continue; } const parsedMessage = parseSarifPlainTextMessage(message); const relatedInformation: DiagnosticRelatedInformation[] = []; const relatedLocationsById: { [k: number]: Sarif.Location } = {}; - - for (let loc of result.relatedLocations || []) { + for (const loc of result.relatedLocations || []) { relatedLocationsById[loc.id!] = loc; } - let resultMessageChunks: string[] = []; + const resultMessageChunks: string[] = []; for (const section of parsedMessage) { if (typeof section === "string") { resultMessageChunks.push(section); } else { resultMessageChunks.push(section.text); - const sarifChunkLoc = parseSarifLocation(relatedLocationsById[section.dest], sourceLocationPrefix); + const sarifChunkLoc = parseSarifLocation( + relatedLocationsById[section.dest], + sourceLocationPrefix + ); if (sarifChunkLoc.t == "NoLocation") { continue; } - const referenceLocation = tryResolveLocation(sarifChunkLoc, databaseItem); - + const referenceLocation = tryResolveLocation( + sarifChunkLoc, + databaseItem + ); if (referenceLocation) { - const related = new DiagnosticRelatedInformation(referenceLocation, - section.text); + const related = new DiagnosticRelatedInformation( + referenceLocation, + section.text + ); relatedInformation.push(related); } } } - const diagnostic = new Diagnostic(resultLocation.range, resultMessageChunks.join(""), DiagnosticSeverity.Warning); + const diagnostic = new Diagnostic( + resultLocation.range, + resultMessageChunks.join(""), + DiagnosticSeverity.Warning + ); diagnostic.relatedInformation = relatedInformation; - diagnostics.push([ - resultLocation.uri, - [diagnostic] - ]); - + diagnostics.push([resultLocation.uri, [diagnostic]]); } this._diagnosticCollection.set(diagnostics); } @@ -442,18 +584,22 @@ export class InterfaceManager extends DisposableObject { return fileUriToWebviewUri(this.getPanel(), Uri.file(path)); } - private convertPathPropertiesToWebviewUris(info: SortedResultSetInfo): SortedResultSetInfo { + private convertPathPropertiesToWebviewUris( + info: SortedResultSetInfo + ): SortedResultSetInfo { return { resultsPath: this.convertPathToWebviewUri(info.resultsPath), sortState: info.sortState }; } - private handleSelectionChange(event: vscode.TextEditorSelectionChangeEvent) { + private handleSelectionChange( + event: vscode.TextEditorSelectionChangeEvent + ): void { if (event.kind === vscode.TextEditorSelectionChangeKind.Command) { return; // Ignore selection events we caused ourselves. } - let editor = vscode.window.activeTextEditor; + const editor = vscode.window.activeTextEditor; if (editor !== undefined) { editor.setDecorations(shownLocationDecoration, []); editor.setDecorations(shownLocationLineDecoration, []); @@ -481,7 +627,7 @@ async function showLocation(loc: ResolvableLocationValue, databaseItem: Database const editor = editorsWithDoc.length > 0 ? editorsWithDoc[0] : await Window.showTextDocument(doc, vscode.ViewColumn.One); - let range = resolvedLocation.range; + const range = resolvedLocation.range; // When highlighting the range, vscode's occurrence-match and bracket-match highlighting will // trigger based on where we place the cursor/selection, and will compete for the user's attention. // For reference: @@ -492,7 +638,7 @@ async function showLocation(loc: ResolvableLocationValue, databaseItem: Database // For single-line ranges, select the whole range, mainly to disable bracket highlighting. // For multi-line ranges, place the cursor at the beginning to avoid visual artifacts from selected line-breaks. // Multi-line ranges are usually large enough to overshadow the noise from bracket highlighting. - let selectionEnd = (range.start.line === range.end.line) + const selectionEnd = (range.start.line === range.end.line) ? range.end : range.start; editor.selection = new vscode.Selection(range.start, selectionEnd); diff --git a/extensions/ql-vscode/src/view/.eslintrc.js b/extensions/ql-vscode/src/view/.eslintrc.js new file mode 100644 index 000000000..cc23503c7 --- /dev/null +++ b/extensions/ql-vscode/src/view/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + ecmaFeatures: { + jsx: true, + }, + env: { + browser: true + }, +} diff --git a/extensions/ql-vscode/src/view/raw-results-table.tsx b/extensions/ql-vscode/src/view/raw-results-table.tsx index 49354b4c4..e45858821 100644 --- a/extensions/ql-vscode/src/view/raw-results-table.tsx +++ b/extensions/ql-vscode/src/view/raw-results-table.tsx @@ -4,7 +4,7 @@ import { RawTableResultSet, ResultValue, vscode } from "./results"; import { SortDirection, RAW_RESULTS_LIMIT, RawResultsSortState } from "../interface-types"; export type RawTableProps = ResultTableProps & { - resultSet: RawTableResultSet, + resultSet: RawTableResultSet; sortState?: RawResultsSortState; }; @@ -67,7 +67,7 @@ export class RawTable extends React.Component { ; } - private toggleSortStateForColumn(index: number) { + private toggleSortStateForColumn(index: number): void { const sortState = this.props.sortState; const prevDirection = sortState && sortState.columnIndex === index ? sortState.sortDirection : undefined; const nextDirection = nextSortDirection(prevDirection); diff --git a/extensions/ql-vscode/src/view/result-table-utils.tsx b/extensions/ql-vscode/src/view/result-table-utils.tsx index 4ea529a1f..888f460b4 100644 --- a/extensions/ql-vscode/src/view/result-table-utils.tsx +++ b/extensions/ql-vscode/src/view/result-table-utils.tsx @@ -7,7 +7,7 @@ import { assertNever } from '../helpers-pure'; export interface ResultTableProps { resultSet: ResultSet; databaseUri: string; - metadata?: QueryMetadata + metadata?: QueryMetadata; resultsPath: string | undefined; sortState?: RawResultsSortState; } @@ -34,7 +34,7 @@ export function jumpToLocationHandler( }; } -export function jumpToLocation(loc: ResolvableLocationValue, databaseUri: string) { +export function jumpToLocation(loc: ResolvableLocationValue, databaseUri: string): void { vscode.postMessage({ t: 'viewSourceFile', loc, diff --git a/extensions/ql-vscode/src/view/result-tables.tsx b/extensions/ql-vscode/src/view/result-tables.tsx index 7ac014a77..449078547 100644 --- a/extensions/ql-vscode/src/view/result-tables.tsx +++ b/extensions/ql-vscode/src/view/result-tables.tsx @@ -12,7 +12,7 @@ export interface ResultTablesProps { rawResultSets: readonly ResultSet[]; interpretation: Interpretation | undefined; database: DatabaseInfo; - metadata?: QueryMetadata + metadata?: QueryMetadata; resultsPath: string; origResultsPaths: ResultsPaths; sortStates: Map; diff --git a/extensions/ql-vscode/src/view/results.tsx b/extensions/ql-vscode/src/view/results.tsx index fa66ead95..900003922 100644 --- a/extensions/ql-vscode/src/view/results.tsx +++ b/extensions/ql-vscode/src/view/results.tsx @@ -4,8 +4,8 @@ import * as bqrs from 'semmle-bqrs'; import { ElementBase, LocationValue, PrimitiveColumnValue, PrimitiveTypeKind, ResultSetSchema, tryGetResolvableLocation } from 'semmle-bqrs'; import { assertNever } from '../helpers-pure'; import { DatabaseInfo, FromResultsViewMsg, Interpretation, IntoResultsViewMsg, SortedResultSetInfo, RawResultsSortState, NavigatePathMsg, QueryMetadata, ResultsPaths } from '../interface-types'; -import { ResultTables } from './result-tables'; import { EventHandlers as EventHandlerList } from './event-handler-list'; +import { ResultTables } from './result-tables'; /** * results.tsx @@ -24,8 +24,8 @@ declare const acquireVsCodeApi: () => VsCodeApi; export const vscode = acquireVsCodeApi(); export interface ResultElement { - label: string, - location?: LocationValue + label: string; + location?: LocationValue; } export interface ResultUri { @@ -37,7 +37,7 @@ export type ResultValue = ResultElement | ResultUri | string; export type ResultRow = ResultValue[]; export type RawTableResultSet = { t: 'RawResultSet' } & RawResultSet; -export type PathTableResultSet = { t: 'SarifResultSet', readonly schema: ResultSetSchema, name: string } & Interpretation; +export type PathTableResultSet = { t: 'SarifResultSet'; readonly schema: ResultSetSchema; name: string } & Interpretation; export type ResultSet = | RawTableResultSet @@ -135,7 +135,7 @@ interface ResultsInfo { * See {@link SetStateMsg.shouldKeepOldResultsWhileRendering}. */ shouldKeepOldResultsWhileRendering: boolean; - metadata?: QueryMetadata + metadata?: QueryMetadata; } interface Results { @@ -212,7 +212,7 @@ class App extends React.Component<{}, ResultsViewState> { private updateStateWithNewResultsInfo(resultsInfo: ResultsInfo): void { this.setState(prevState => { - const stateWithDisplayedResults = (displayedResults: ResultsState) => ({ + const stateWithDisplayedResults = (displayedResults: ResultsState): ResultsViewState => ({ displayedResults, isExpectingResultsUpdate: prevState.isExpectingResultsUpdate, nextResultsInfo: resultsInfo @@ -245,7 +245,7 @@ class App extends React.Component<{}, ResultsViewState> { } let results: Results | null = null; - let statusText: string = ''; + let statusText = ''; try { results = { resultSets: await this.getResultSets(resultsInfo), @@ -304,7 +304,7 @@ class App extends React.Component<{}, ResultsViewState> { [key, sortedResultSetInfo.sortState])); } - render() { + render(): JSX.Element { const displayedResults = this.state.displayedResults; if (displayedResults.results !== null && displayedResults.resultsInfo !== null) { return { } } - componentDidMount() { + componentDidMount(): void { this.vscodeMessageHandler = evt => this.handleMessage(evt.data as IntoResultsViewMsg); window.addEventListener('message', this.vscodeMessageHandler); } - componentWillUnmount() { + componentWillUnmount(): void { if (this.vscodeMessageHandler) { window.removeEventListener('message', this.vscodeMessageHandler); } diff --git a/extensions/ql-vscode/src/vscode-tests/.eslintrc.js b/extensions/ql-vscode/src/vscode-tests/.eslintrc.js new file mode 100644 index 000000000..8f4efbda1 --- /dev/null +++ b/extensions/ql-vscode/src/vscode-tests/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + env: { + mocha: true + } +} diff --git a/extensions/ql-vscode/test/.eslintrc.js b/extensions/ql-vscode/test/.eslintrc.js new file mode 100644 index 000000000..8f4efbda1 --- /dev/null +++ b/extensions/ql-vscode/test/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + env: { + mocha: true + } +} diff --git a/extensions/ql-vscode/tsconfig.json b/extensions/ql-vscode/tsconfig.json index aa011be95..bbda3c57a 100644 --- a/extensions/ql-vscode/tsconfig.json +++ b/extensions/ql-vscode/tsconfig.json @@ -1,3 +1,3 @@ { "extends": "./node_modules/typescript-config/extension.tsconfig.json" -} \ No newline at end of file +}