Fix eslint rules
* import/named rule is used only for .js files - the rule doesn't work
correctly with .ts files and ts compiler checks imports in .ts anyway.
* fix goog-module-id rule
* eslint now reports problems in .d.ts files
Change-Id: I95d4c1692f1aabdb460dc2e85a55ac5daae72ef0
diff --git a/polygerrit-ui/app/.eslintrc.js b/polygerrit-ui/app/.eslintrc.js
index cc9f304..932997e 100644
--- a/polygerrit-ui/app/.eslintrc.js
+++ b/polygerrit-ui/app/.eslintrc.js
@@ -149,7 +149,6 @@
}
}
}],
- "import/named": 2,
"import/no-self-import": 2,
// The no-cycle rule is slow, because it doesn't cache dependencies.
// Disable it.
@@ -183,6 +182,7 @@
// The rule is required for .js files only, because typescript compiler
// always checks import.
"import/no-unresolved": 2,
+ "import/named": 2,
},
"globals": {
"goog": "readonly",
@@ -193,10 +193,10 @@
"extends": [require.resolve("gts/.eslintrc.json")],
"rules": {
// The following rules is required to match internal google rules
- "@typescript-eslint/restrict-plus-operands": "error"
+ "@typescript-eslint/restrict-plus-operands": "error",
},
"parserOptions": {
- "project": path.resolve(__dirname, "./tsconfig.json"),
+ "project": path.resolve(__dirname, "./tsconfig_eslint.json"),
}
},
{
@@ -209,6 +209,13 @@
}
},
{
+ "files": ["**/*.d.ts"],
+ "rules": {
+ // See details in the //tools/js/eslint-rules/report-ts-error.js file.
+ "report-ts-error": "error",
+ }
+ },
+ {
"files": ["*.html", "test.js", "test-infra.js", "template_test.js"],
"rules": {
"jsdoc/require-file-overview": "off"
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index fb2bd73..054033c 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -114,6 +114,8 @@
".eslintrc.js",
".prettierrc.js",
".eslint-ts-resolver.js",
+ "tsconfig_eslint.json",
+ # tsconfig_eslint.json extends tsconfig.json, pass it as a dependency
"tsconfig.json",
],
extensions = [
diff --git a/polygerrit-ui/app/tsconfig_eslint.json b/polygerrit-ui/app/tsconfig_eslint.json
new file mode 100644
index 0000000..7cc99c7
--- /dev/null
+++ b/polygerrit-ui/app/tsconfig_eslint.json
@@ -0,0 +1,11 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "skipLibCheck": false, /* This is required for report-ts-error.js.
+ See details in the //tools/js/eslint-rules/report-ts-error.js file.*/
+ "baseUrl": "../../external/ui_npm/node_modules" /* Only for bazel.
+ Compiler will try to use it to resolve module name and if it fail - will
+ fallback to a default behavior
+ (https://github.com/microsoft/TypeScript/issues/5039)*/
+ }
+}
diff --git a/tools/js/eslint-rules/goog-module-id.js b/tools/js/eslint-rules/goog-module-id.js
index 272e664..56cd645 100644
--- a/tools/js/eslint-rules/goog-module-id.js
+++ b/tools/js/eslint-rules/goog-module-id.js
@@ -106,7 +106,8 @@
}
const expectedName = 'polygerrit.' +
filename.slice(index + pathStart.length, -jsExt.length)
- .replace('/', '.');
+ .replace(/\//g, '.') // Replace all occurrences of '/' with '.'
+ .replace(/-/g, '$2d'); // Replace all occurrences of '-' with '$2d'
if(argument.value !== expectedName) {
context.report({
message: `Invalid module id. It must be '${expectedName}'.`,
diff --git a/tools/js/eslint-rules/report-ts-error.js b/tools/js/eslint-rules/report-ts-error.js
new file mode 100644
index 0000000..48dddf4
--- /dev/null
+++ b/tools/js/eslint-rules/report-ts-error.js
@@ -0,0 +1,101 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// While we are migrating to typescript, gerrit can have .d.ts files.
+// The option "skipLibCheck" is set to true In the tsconfig.json.
+// This is required, because we want to skip type checking in node_modules
+// directory - some .d.ts files in 3rd-party modules are incorrect.
+// Unfortunately, this options also excludes our own .d.ts files from type
+// checking. This rule reports all .ts errors in a file as tslint errors.
+
+function getMassageTextFromChain(chainNode, prefix) {
+ let nestedMessages = prefix + chainNode.messageText;
+ if (chainNode.next && chainNode.next.length > 0) {
+ nestedMessages += "\n";
+ for (const node of chainNode.next) {
+ nestedMessages +=
+ getMassageTextFromChain(node, prefix + " ");
+ if(!nestedMessages.endsWith('\n')) {
+ nestedMessages += "\n";
+ }
+ }
+ }
+ return nestedMessages;
+}
+
+function getMessageText(diagnostic) {
+ if (typeof diagnostic.messageText === 'string') {
+ return diagnostic.messageText;
+ }
+ return getMassageTextFromChain(diagnostic.messageText, "");
+}
+
+function getDiagnosticStartAndEnd(diagnostic) {
+ if(diagnostic.start) {
+ const file = diagnostic.file;
+ const start = file.getLineAndCharacterOfPosition(diagnostic.start);
+ const length = diagnostic.length ? diagnostic.length : 0;
+ return {
+ start,
+ end: file.getLineAndCharacterOfPosition(diagnostic.start + length),
+ };
+ }
+ return {
+ start: {line:0, character: 0},
+ end: {line:0, character: 0},
+ }
+}
+
+module.exports = {
+ meta: {
+ type: "problem",
+ docs: {
+ description: "Reports all typescript problems as linter problems",
+ category: ".d.ts",
+ recommended: false
+ },
+ schema: [],
+ },
+ create: function (context) {
+ const program = context.parserServices.program;
+ return {
+ Program: function(node) {
+ const sourceFile =
+ context.parserServices.esTreeNodeToTSNodeMap.get(node);
+ const allDiagnostics = [
+ ...program.getDeclarationDiagnostics(sourceFile),
+ ...program.getSemanticDiagnostics(sourceFile)];
+ for(const diagnostic of allDiagnostics) {
+ const {start, end } = getDiagnosticStartAndEnd(diagnostic);
+ context.report({
+ message: getMessageText(diagnostic),
+ loc: {
+ start: {
+ line: start.line + 1,
+ column: start.character,
+ },
+ end: {
+ line: end.line + 1,
+ column: end.character,
+ }
+ }
+ });
+ }
+ },
+ };
+ }
+};