* 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
161 lines
4.5 KiB
JavaScript
161 lines
4.5 KiB
JavaScript
/**
|
|
* @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);
|
|
}
|
|
};
|
|
},
|
|
};
|