ui5plugin-linter
Version:
151 lines (150 loc) • 7.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TagLinter = void 0;
const __1 = require("../../..");
const Linter_1 = require("../../Linter");
const XMLLinter_1 = require("./abstraction/XMLLinter");
class TagLinter extends XMLLinter_1.XMLLinter {
constructor() {
super(...arguments);
this.className = Linter_1.XMLLinters.TagLinter;
}
_getErrors(document) {
const errors = [];
const XMLFile = this._parser.textDocumentTransformer.toXMLFile(document);
if (XMLFile) {
const tags = this._parser.xmlParser.getAllTags(XMLFile);
tags.forEach((tag, index) => {
const previousTag = tags[index - 1];
if (!previousTag || previousTag.text !== "<!-- @ui5ignore -->") {
errors.push(...this._getClassNameErrors(tag, XMLFile));
}
});
}
return errors;
}
_getClassNameErrors(tag, XMLFile) {
const documentText = XMLFile.content;
const errors = [];
const tagClass = this._parser.xmlParser.getFullClassNameFromTag(tag, XMLFile);
const documentClassName = this._parser.fileReader.getClassNameFromPath(XMLFile.fsPath) || "";
if (tagClass.startsWith("http://www.w3.org/1999/xhtml.")) {
return errors;
}
if (!tagClass) {
const range = __1.RangeAdapter.offsetsRange(documentText, tag.positionBegin, tag.positionEnd + 1);
if (range && this._parser.xmlParser.getIfPositionIsNotInComments(XMLFile, tag.positionBegin)) {
const prefix = this._parser.xmlParser.getTagPrefix(tag.text);
errors.push({
code: "UI5plugin",
message: `"${prefix}" prefix is not defined`,
source: this.className,
severity: this._configHandler.getSeverity(this.className),
range: range,
className: documentClassName,
fsPath: XMLFile.fsPath
});
}
}
else {
const tagParts = tagClass.split(".");
const tagName = tagParts.pop();
const tagPrefixLibrary = tagParts.join(".");
const isAggregation = tagName && tagName[0] ? tagName[0].toLowerCase() === tagName[0] : false;
if (!isAggregation) {
this._lintClass(tagClass, documentText, tag, XMLFile, errors, documentClassName);
}
else {
this._lintAggregation(tag, XMLFile, tagName, tagPrefixLibrary, documentText, errors, documentClassName);
}
}
return errors;
}
_lintAggregation(tag, XMLFile, tagName, tagPrefixLibrary, documentText, errors, documentClassName) {
let position = tag.positionBegin;
if (tag.text.startsWith("</")) {
position = tag.positionEnd;
}
const parentTag = this._parser.xmlParser.getParentTagAtPosition(XMLFile, position - 1);
if (parentTag.text && tagName) {
const parentTagPrefix = this._parser.xmlParser.getTagPrefix(parentTag.text);
const tagClass = this._parser.xmlParser.getFullClassNameFromTag(parentTag, XMLFile);
if (tagClass) {
let errorText;
const parentTagPrefixLibrary = this._parser.xmlParser.getLibraryPathFromTagPrefix(XMLFile, parentTagPrefix, parentTag.positionBegin);
const aggregation = this._findAggregation(tagClass, tagName);
if (!aggregation) {
errorText = `"${tagName}" aggregation doesn't exist in "${tagClass}"`;
}
else if (parentTagPrefixLibrary !== tagPrefixLibrary) {
errorText = `Library "${parentTagPrefixLibrary}" of class "${tagClass}" doesn't match with aggregation tag library "${tagPrefixLibrary}"`;
}
if (errorText) {
const range = __1.RangeAdapter.offsetsRange(documentText, tag.positionBegin, tag.positionEnd + 1);
if (range && this._parser.xmlParser.getIfPositionIsNotInComments(XMLFile, tag.positionBegin)) {
errors.push({
code: "UI5plugin",
message: errorText,
source: this.className,
range: range,
severity: this._configHandler.getSeverity(this.className),
className: documentClassName,
fsPath: XMLFile.fsPath
});
}
}
}
}
}
_lintClass(tagClass, documentText, tag, XMLFile, errors, documentClassName) {
const UIClass = this._parser.classFactory.getUIClass(tagClass);
if (!UIClass.classExists && !this._isClassException(tagClass)) {
this._lintIfClassExists(documentText, tag, XMLFile, errors, tagClass, documentClassName);
}
else if (UIClass.classExists && UIClass.deprecated && !this._isClassException(tagClass)) {
this._lintIfClassIsDeprecated(documentText, tag, XMLFile, errors, tagClass, documentClassName);
}
}
_lintIfClassIsDeprecated(documentText, tag, XMLFile, errors, tagClass, documentClassName) {
const range = __1.RangeAdapter.offsetsRange(documentText, tag.positionBegin, tag.positionEnd + 1);
if (range && this._parser.xmlParser.getIfPositionIsNotInComments(XMLFile, tag.positionBegin)) {
errors.push({
code: "UI5plugin",
message: `"${tagClass}" class is deprecated`,
source: this.className,
severity: this._configHandler.getSeverity(this.className),
range: range,
className: documentClassName,
fsPath: XMLFile.fsPath,
tags: [Linter_1.DiagnosticTag.Deprecated]
});
}
}
_lintIfClassExists(documentText, tag, XMLFile, errors, tagClass, documentClassName) {
const range = __1.RangeAdapter.offsetsRange(documentText, tag.positionBegin, tag.positionEnd + 1);
if (range && this._parser.xmlParser.getIfPositionIsNotInComments(XMLFile, tag.positionBegin)) {
errors.push({
code: "UI5plugin",
message: `"${tagClass}" class doesn't exist`,
source: this.className,
severity: this._configHandler.getSeverity(this.className),
range: range,
className: documentClassName,
fsPath: XMLFile.fsPath
});
}
}
_findAggregation(className, aggregationName) {
const UIClass = this._parser.classFactory.getUIClass(className);
let aggregation = UIClass.aggregations.find(aggregation => aggregation.name === aggregationName);
if (!aggregation && UIClass.parentClassNameDotNotation) {
aggregation = this._findAggregation(UIClass.parentClassNameDotNotation, aggregationName);
}
return aggregation;
}
_isClassException(className) {
const exceptions = ["sap.ui.core.FragmentDefinition"];
return exceptions.includes(className);
}
}
exports.TagLinter = TagLinter;