@ui5/linter
Version:
A static code analysis tool for UI5
150 lines • 5.62 kB
JavaScript
import { AttributeType } from "sax-wasm";
import { ChangeAction } from "../../../utils/textChanges.js";
import { HtmlFix } from "./HtmlFix.js";
/**
* Fix to remove an attribute from an HTML tag.
* @param tag The surrounding tag from which the attribute should be removed.
* @param attr The attribute to be removed.
*/
export default class RemoveAttributeFix extends HtmlFix {
startPositionDetail;
endPositionDetail;
constructor(tag, attr) {
super();
const startPos = this._calculateStartPos(tag, attr);
const endPos = this._calculateEndPos(attr);
this.startPositionDetail = startPos;
this.endPositionDetail = endPos;
}
/**
* This will prepare the start pos of the removal.
* This is needed to ensure there are no empty lines or whitespaces left after removal.
*/
_calculateStartPos(tag, attr) {
let startPos;
const attrIndex = tag.attributes.indexOf(attr);
const previousAttr = attrIndex > 0 ? tag.attributes[attrIndex - 1] : undefined;
const subsequentAttr = tag.attributes[attrIndex + 1];
if (!previousAttr) {
// If there is no previous attribute (attribute is first), we remove the current attribute
// and all whitespace until the end of the tag name.
startPos = {
line: tag.openStart.line,
character: tag.openStart.character + tag.name.length + 1,
};
}
else {
// If there is a previous attribute, we remove the current attribute
// and all whitespace until the previous attribute.
switch (previousAttr.type) {
case AttributeType.SingleQuoted:
case AttributeType.DoubleQuoted:
startPos = {
line: previousAttr.value.end.line,
character: previousAttr.value.end.character + 1,
};
break;
case AttributeType.NoQuotes:
startPos = {
line: previousAttr.value.end.line,
character: previousAttr.value.end.character,
};
break;
case AttributeType.NoValue:
startPos = {
line: previousAttr.name.end.line,
character: previousAttr.name.end.character,
};
break;
}
}
// Edge case: no space w/ NoValues or NoQuotes
const edgeCaseStart = this._getEdgeCaseStartPos(tag, previousAttr, attr, subsequentAttr);
if (edgeCaseStart) {
startPos = edgeCaseStart;
}
if (!startPos) {
throw new Error("Could not calculate start position for attribute removal");
}
return startPos;
}
/**
* This will prepare the end pos of the removal.
*/
_calculateEndPos(attr) {
let endPos;
switch (attr.type) {
case AttributeType.SingleQuoted:
case AttributeType.DoubleQuoted:
endPos = {
line: attr.value.end.line,
character: attr.value.end.character + 1,
};
break;
case AttributeType.NoQuotes:
endPos = {
line: attr.value.end.line,
character: attr.value.end.character,
};
break;
case AttributeType.NoValue:
endPos = {
line: attr.name.end.line,
character: attr.name.end.character,
};
break;
}
if (!endPos) {
throw new Error("Could not calculate end position for attribute removal");
}
return endPos;
}
calculateSourceCodeRange(toPosition) {
this.startPos = toPosition(this.startPositionDetail);
this.endPos = toPosition(this.endPositionDetail);
}
generateChanges() {
if (this.startPos === undefined || this.endPos === undefined) {
throw new Error("Start and end position are not defined");
}
return {
action: ChangeAction.DELETE,
start: this.startPos,
end: this.endPos,
};
}
_getEdgeCaseStartPos(tag, previousAttr, attr, subsequentAttr) {
// Edge Case 1: attr=abc attr="def"ignore=xyz
// --> attr=abc ignore=xyz
// Edge Case 2: attr attr="def"ignore=xyz
// --> attr ignore=xyz
if (!subsequentAttr) {
return undefined;
}
if (subsequentAttr.name.end.line != attr.value.end.line) {
return undefined;
}
if (subsequentAttr.name.start.character != attr.value.end.character + 1) {
return undefined;
}
if (!previousAttr) {
return {
line: tag.openStart.line,
character: tag.openStart.character + tag.name.length + 2,
};
}
else if (previousAttr.type === AttributeType.NoValue) {
return {
line: previousAttr.name.end.line,
character: previousAttr.name.end.character + 1,
};
}
else if (previousAttr.type === AttributeType.NoQuotes) {
return {
line: previousAttr.value.end.line,
character: previousAttr.value.end.character + 1,
};
}
}
}
//# sourceMappingURL=RemoveAttributeFix.js.map