UNPKG

@ui5/linter

Version:

A static code analysis tool for UI5

113 lines 4.21 kB
import ts from "typescript"; import { ChangeAction } from "../../../autofix/autofix.js"; import Fix from "./Fix.js"; import { isConditionalAccess } from "../utils/utils.js"; ; /** * Fix a global property access. Requires a module name which will be imported and replaces the defined property access. * The property access is in the order of the AST, e.g. ["core", "ui", "sap"] */ export default class GlobalFix extends Fix { params; startPos; endPos; moduleIdentifier; sourcePosition; isConditional; constructor(params) { super(); this.params = params; } visitLinterNode(node, sourcePosition) { if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node) && !ts.isCallExpression(node)) { return false; } if (this.params.resourcePath === `/resources/${this.params.moduleName}.js` || this.params.resourcePath === `/resources/${this.params.moduleName}.ts`) { // Prevent adding imports to the module itself return false; } // Check for usage of "delete" keyword with the module export, which is not fixable // as only an identifier would remain after the autofix, which would not be valid. if (ts.isDeleteExpression(node.parent) && node.parent.expression === node) { return false; } // Check whether the access is conditional / probing / lazy this.isConditional = isConditionalAccess(node); this.sourcePosition = sourcePosition; return true; } getNodeSearchParameters() { if (this.sourcePosition === undefined) { throw new Error("Position for search is not defined"); } return { nodeTypes: [ts.SyntaxKind.PropertyAccessExpression, ts.SyntaxKind.ElementAccessExpression], position: this.sourcePosition, }; } visitAutofixNode(node, position, sourceFile) { if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node)) { return false; } const firstPart = this.params.propertyAccessStack[0]; // Check whether first part matches, that's all we need for start and end positions if ((ts.isPropertyAccessExpression(node) && node.name.text === firstPart) || (ts.isElementAccessExpression(node) && ts.isStringLiteralLike(node.argumentExpression) && node.argumentExpression.text === firstPart)) { this.startPos = node.getStart(sourceFile); this.endPos = node.getEnd(); return true; } return false; } getAffectedSourceCodeRange() { if (this.startPos === undefined || this.endPos === undefined) { throw new Error("Start and end position are not defined"); } return { start: this.startPos, end: this.endPos, }; } setIdentifierForDependency(identifier) { this.moduleIdentifier = identifier; } getNewModuleDependencies() { if (this.startPos === undefined) { throw new Error("Start position is not defined"); } if (!this.params.moduleName) { return; } return { moduleName: this.params.moduleName, usagePosition: this.startPos, blockNewImport: this.isConditional, }; } getNewGlobalAccess() { return undefined; } setIdentifierForGlobal() { return; } generateChanges() { if (this.startPos === undefined || this.endPos === undefined) { throw new Error("Start and end position are not defined"); } if (!this.moduleIdentifier) { // Identifier has not been set. This can happen if the relevant position is not inside a // module definition or require block. Therefore the fix can not be applied. return; } const value = this.moduleIdentifier; return { action: ChangeAction.REPLACE, start: this.startPos, end: this.endPos, value, }; } } //# sourceMappingURL=GlobalFix.js.map