Cleanup eslint rules and fix some eslint warnings
Change-Id: If4aeaa1bba276ed9c3bfea417af47110f51591f9
This commit is contained in:
committed by
Luca Milanesio
parent
68aac7fb2e
commit
f5d728ede5
@@ -300,8 +300,6 @@ module.exports = {
|
||||
{
|
||||
"files": [
|
||||
"*.html",
|
||||
"common-test-setup.js",
|
||||
"common-test-setup-karma.js",
|
||||
"*_test.js",
|
||||
"a11y-test-utils.js",
|
||||
],
|
||||
|
||||
@@ -127,8 +127,8 @@ export function initErrorReporter(appContext: AppContext) {
|
||||
oldOnError(msg, url, line, column, error);
|
||||
}
|
||||
if (error) {
|
||||
line = line || (error as any).lineNumber;
|
||||
column = column || (error as any).columnNumber;
|
||||
line = line || error.lineNumber;
|
||||
column = column || error.columnNumber;
|
||||
let shortenedErrorStack = msg;
|
||||
if (error.stack) {
|
||||
const errorStackLines = error.stack.split('\n');
|
||||
|
||||
@@ -86,6 +86,9 @@ function flushImpl(callback?: () => void): Promise<void> | void {
|
||||
// Ideally, this function would be a call to Polymer.dom.flush, but that
|
||||
// doesn't support a callback yet
|
||||
// (https://github.com/Polymer/polymer-dev/issues/851)
|
||||
// The type is used only in one place, disable eslint warning instead of
|
||||
// creating an interface
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).Polymer.dom.flush();
|
||||
if (callback) {
|
||||
nativeSetTimeout(callback, 0);
|
||||
|
||||
@@ -182,9 +182,7 @@ function checkChildAllowed(element: Element) {
|
||||
`The following node remains in document after the test:
|
||||
${element.tagName}
|
||||
Outer HTML:
|
||||
${element.outerHTML},
|
||||
Stack trace:
|
||||
${(element as any).stackTrace}`
|
||||
${element.outerHTML}`
|
||||
);
|
||||
}
|
||||
function checkGlobalSpace() {
|
||||
|
||||
@@ -75,50 +75,50 @@ declare global {
|
||||
// TODO(TS): should clean up those and removing them may break certain plugin behaviors
|
||||
// TODO(TS): as @brohlfs suggested, to avoid importing anything from elements/ to types/
|
||||
// use any for them for now
|
||||
GrDisplayNameUtils: any;
|
||||
GrAnnotation: any;
|
||||
GrAttributeHelper: any;
|
||||
GrDiffLine: any;
|
||||
GrDiffLineType: any;
|
||||
GrDiffGroup: any;
|
||||
GrDiffGroupType: any;
|
||||
GrDiffBuilder: any;
|
||||
GrDiffBuilderSideBySide: any;
|
||||
GrDiffBuilderImage: any;
|
||||
GrDiffBuilderUnified: any;
|
||||
GrDiffBuilderBinary: any;
|
||||
GrChangeActionsInterface: any;
|
||||
GrChangeReplyInterface: any;
|
||||
GrEditConstants: any;
|
||||
GrDomHooksManager: any;
|
||||
GrDomHook: any;
|
||||
GrEtagDecorator: any;
|
||||
GrThemeApi: any;
|
||||
SiteBasedCache: any;
|
||||
FetchPromisesCache: any;
|
||||
GrRestApiHelper: any;
|
||||
GrLinkTextParser: any;
|
||||
GrPluginEndpoints: any;
|
||||
GrReviewerUpdatesParser: any;
|
||||
GrPopupInterface: any;
|
||||
GrCountStringFormatter: any;
|
||||
GrReviewerSuggestionsProvider: any;
|
||||
util: any;
|
||||
Auth: any;
|
||||
EventEmitter: any;
|
||||
GrAdminApi: any;
|
||||
GrAnnotationActionsContext: any;
|
||||
GrAnnotationActionsInterface: any;
|
||||
GrChangeMetadataApi: any;
|
||||
GrEmailSuggestionsProvider: any;
|
||||
GrGroupSuggestionsProvider: any;
|
||||
GrEventHelper: any;
|
||||
GrPluginRestApi: any;
|
||||
GrRepoApi: any;
|
||||
GrSettingsApi: any;
|
||||
GrStylesApi: any;
|
||||
PluginLoader: any;
|
||||
GrPluginActionContext: any;
|
||||
GrDisplayNameUtils: unknown;
|
||||
GrAnnotation: unknown;
|
||||
GrAttributeHelper: unknown;
|
||||
GrDiffLine: unknown;
|
||||
GrDiffLineType: unknown;
|
||||
GrDiffGroup: unknown;
|
||||
GrDiffGroupType: unknown;
|
||||
GrDiffBuilder: unknown;
|
||||
GrDiffBuilderSideBySide: unknown;
|
||||
GrDiffBuilderImage: unknown;
|
||||
GrDiffBuilderUnified: unknown;
|
||||
GrDiffBuilderBinary: unknown;
|
||||
GrChangeActionsInterface: unknown;
|
||||
GrChangeReplyInterface: unknown;
|
||||
GrEditConstants: unknown;
|
||||
GrDomHooksManager: unknown;
|
||||
GrDomHook: unknown;
|
||||
GrEtagDecorator: unknown;
|
||||
GrThemeApi: unknown;
|
||||
SiteBasedCache: unknown;
|
||||
FetchPromisesCache: unknown;
|
||||
GrRestApiHelper: unknown;
|
||||
GrLinkTextParser: unknown;
|
||||
GrPluginEndpoints: unknown;
|
||||
GrReviewerUpdatesParser: unknown;
|
||||
GrPopupInterface: unknown;
|
||||
GrCountStringFormatter: unknown;
|
||||
GrReviewerSuggestionsProvider: unknown;
|
||||
util: unknown;
|
||||
Auth: unknown;
|
||||
EventEmitter: unknown;
|
||||
GrAdminApi: unknown;
|
||||
GrAnnotationActionsContext: unknown;
|
||||
GrAnnotationActionsInterface: unknown;
|
||||
GrChangeMetadataApi: unknown;
|
||||
GrEmailSuggestionsProvider: unknown;
|
||||
GrGroupSuggestionsProvider: unknown;
|
||||
GrEventHelper: unknown;
|
||||
GrPluginRestApi: unknown;
|
||||
GrRepoApi: unknown;
|
||||
GrSettingsApi: unknown;
|
||||
GrStylesApi: unknown;
|
||||
PluginLoader: unknown;
|
||||
GrPluginActionContext: unknown;
|
||||
_apiUtils: {};
|
||||
}
|
||||
|
||||
@@ -138,4 +138,9 @@ declare global {
|
||||
// TODO(TS): replace with composedPath if possible
|
||||
readonly path: EventTarget[];
|
||||
}
|
||||
|
||||
interface Error {
|
||||
lineNumber?: number; // non-standard property
|
||||
columnNumber?: number; // non-standard property
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ export function hasOwnProperty(obj: any, prop: PropertyKey) {
|
||||
}
|
||||
|
||||
// TODO(TS): move to common types once we have type utils
|
||||
// tslint:disable-next-line:no-any Required for constructor signature.
|
||||
// Required for constructor signature.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type Constructor<T> = new (...args: any[]) => T;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const jsExt = '.js';
|
||||
|
||||
class NonJsValidator {
|
||||
onProgramEnd(context, node) {
|
||||
}
|
||||
onGoogDeclareModuleId(context, node) {
|
||||
context.report({
|
||||
message: 'goog.declareModuleId is allowed only in .js files',
|
||||
node: node,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class JsOnlyValidator {
|
||||
onProgramEnd(context, node) {
|
||||
}
|
||||
onGoogDeclareModuleId(context, node) {
|
||||
context.report({
|
||||
message: 'goog.declareModuleId present, but .d.ts file doesn\'t exist. '
|
||||
+ 'Either remove goog.declareModuleId or add the .d.ts file.',
|
||||
node: node,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class JsWithDtsValidator {
|
||||
constructor() {
|
||||
this._googDeclareModuleIdExists = false;
|
||||
}
|
||||
onProgramEnd(context, node) {
|
||||
if(!this._googDeclareModuleIdExists) {
|
||||
context.report({
|
||||
message: 'goog.declareModuleId(...) is missed. ' +
|
||||
'Either add it or remove the associated .d.ts file.',
|
||||
node: node,
|
||||
})
|
||||
}
|
||||
}
|
||||
onGoogDeclareModuleId(context, node) {
|
||||
if(this._googDeclareModuleIdExists) {
|
||||
context.report({
|
||||
message: 'Duplicated goog.declareModuleId.',
|
||||
node: node,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const filename = context.getFilename();
|
||||
this._googDeclareModuleIdExists = true;
|
||||
|
||||
const scope = context.getScope();
|
||||
if(scope.type !== 'global' && scope.type !== 'module') {
|
||||
context.report({
|
||||
message: 'goog.declareModuleId is allowed only at the root level.',
|
||||
node: node,
|
||||
});
|
||||
// no return - other problems are possible
|
||||
}
|
||||
if(node.arguments.length !== 1) {
|
||||
context.report({
|
||||
message: 'goog.declareModuleId must have exactly one parameter.',
|
||||
node: node,
|
||||
});
|
||||
if(node.arguments.length === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const argument = node.arguments[0];
|
||||
if(argument.type !== 'Literal') {
|
||||
context.report({
|
||||
message: 'The argument for the declareModuleId method '
|
||||
+ 'must be a string literal.',
|
||||
node: argument,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const pathStart = '/polygerrit-ui/app/';
|
||||
const index = filename.lastIndexOf(pathStart);
|
||||
if(index < 0) {
|
||||
context.report({
|
||||
message: 'The file located outside of polygerrit-ui/app directory. ' +
|
||||
'Please check eslint config.',
|
||||
node: argument,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const expectedName = 'polygerrit.' +
|
||||
filename.slice(index + pathStart.length, -jsExt.length)
|
||||
.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}'.`,
|
||||
node: argument,
|
||||
fix: function(fixer) {
|
||||
return fixer.replaceText(argument, `'${expectedName}'`);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Check that goog.declareModuleId is valid',
|
||||
category: 'TS imports JS errors',
|
||||
recommended: false,
|
||||
},
|
||||
fixable: "code",
|
||||
schema: [],
|
||||
},
|
||||
create: function (context) {
|
||||
let fileValidator;
|
||||
return {
|
||||
Program: function(node) {
|
||||
const filename = context.getFilename();
|
||||
if(filename.endsWith(jsExt)) {
|
||||
const dtsFilename = filename.slice(0, -jsExt.length) + ".d.ts";
|
||||
if(fs.existsSync(dtsFilename)) {
|
||||
fileValidator = new JsWithDtsValidator();
|
||||
} else {
|
||||
fileValidator = new JsOnlyValidator();
|
||||
}
|
||||
}
|
||||
else {
|
||||
fileValidator = new NonJsValidator();
|
||||
}
|
||||
},
|
||||
"Program:exit": function(node) {
|
||||
fileValidator.onProgramEnd(context, node);
|
||||
fileValidator = null;
|
||||
},
|
||||
'ExpressionStatement > CallExpression[callee.property.name="declareModuleId"][callee.object.name="goog"]': function(node) {
|
||||
fileValidator.onGoogDeclareModuleId(context, node);
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* @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,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -1,109 +0,0 @@
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
function checkImportValid(context, node) {
|
||||
const file = context.getFilename();
|
||||
const importSource = node.source.value;
|
||||
|
||||
if(importSource.startsWith('/')) {
|
||||
return {
|
||||
message: 'Do not use absolute path for import.',
|
||||
};
|
||||
}
|
||||
|
||||
const targetFile = path.resolve(path.dirname(file), importSource);
|
||||
const extName = path.extname(targetFile);
|
||||
// There is a polymer.dom.js file, so .dom is not an extension
|
||||
if(extName !== '' && !targetFile.endsWith('polymer.dom')) {
|
||||
return {
|
||||
message: 'Do not specify extensions for import path.',
|
||||
fix: function(fixer) {
|
||||
return fixer.replaceText(node.source, `'${importSource.slice(0, -extName.length)}'`);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if(!importSource.startsWith('./') && !importSource.startsWith('../')) {
|
||||
// Import from node_modules - nothing else to check
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if(fs.existsSync(targetFile + ".ts")) {
|
||||
// .ts file exists - nothing to check
|
||||
return null;
|
||||
}
|
||||
|
||||
const jsFileExists = fs.existsSync(targetFile + '.js');
|
||||
const dtsFileExists = fs.existsSync(targetFile + '.d.ts');
|
||||
|
||||
if(jsFileExists && !dtsFileExists) {
|
||||
return {
|
||||
message: `The '${importSource}.d.ts' file doesn't exist.`
|
||||
};
|
||||
}
|
||||
|
||||
if(!jsFileExists && dtsFileExists) {
|
||||
return {
|
||||
message: `The '${importSource}.js' file doesn't exist.`
|
||||
};
|
||||
}
|
||||
// If both files (.js and .d.ts) don't exist, the error is reported by
|
||||
// the typescript compiler. Do not report anything from the rule.
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
docs: {
|
||||
description: "Check that TS file can import specific JS file",
|
||||
category: "TS imports JS errors",
|
||||
recommended: false
|
||||
},
|
||||
schema: [],
|
||||
fixable: "code",
|
||||
},
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function(node) {
|
||||
const filename = context.getFilename();
|
||||
if(filename.endsWith('.ts') && !filename.endsWith('.d.ts')) {
|
||||
return;
|
||||
}
|
||||
context.report({
|
||||
message: 'The rule must be used only with .ts files. ' +
|
||||
'Check eslint settings.',
|
||||
node: node,
|
||||
});
|
||||
},
|
||||
ImportDeclaration: function (node) {
|
||||
const importProblem = checkImportValid(context, node);
|
||||
if(importProblem) {
|
||||
context.report({
|
||||
message: importProblem.message,
|
||||
node: node.source,
|
||||
fix: importProblem.fix,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user