@abaplint/core
Version:
abaplint - Core API
84 lines • 4.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.StringTemplate = void 0;
const nodes_1 = require("../../nodes");
const basic_1 = require("../../types/basic");
const Expressions = require("../../2_statements/expressions");
const source_1 = require("./source");
const _type_utils_1 = require("../_type_utils");
const _syntax_input_1 = require("../_syntax_input");
const Tokens = require("../../1_lexer/tokens");
class StringTemplate {
static runSyntax(node, input) {
const typeUtils = new _type_utils_1.TypeUtils(input.scope);
const ret = basic_1.StringType.get();
for (const child of node.getChildren()) {
if (child instanceof nodes_1.ExpressionNode && child.get() instanceof Expressions.StringTemplateSource) {
const s = child.findDirectExpression(Expressions.Source);
const type = source_1.Source.runSyntax(s, input, ret);
if (type === undefined) {
const message = "No target type determined";
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
else if ((typeUtils.isCharLike(type) === false
&& typeUtils.isHexLike(type) === false
&& !(type instanceof basic_1.UTCLongType))
|| type instanceof basic_1.StructureType) {
const message = "String template, not character like, " + type.constructor.name;
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
const format = child.findDirectExpression(Expressions.StringTemplateFormatting);
const formatConcat = format === null || format === void 0 ? void 0 : format.concatTokens();
for (const formatSource of (format === null || format === void 0 ? void 0 : format.findAllExpressions(Expressions.Source)) || []) {
source_1.Source.runSyntax(formatSource, input);
}
if (format
&& (formatConcat === null || formatConcat === void 0 ? void 0 : formatConcat.includes("ALPHA = "))
&& !(type instanceof basic_1.UnknownType)
&& !(type instanceof basic_1.VoidType)
&& !(type instanceof basic_1.StringType)
&& !(type instanceof basic_1.CLikeType)
&& !(type instanceof basic_1.CharacterType)
&& !(type instanceof basic_1.NumericGenericType)
&& !(type instanceof basic_1.NumericType)
&& !(type instanceof basic_1.AnyType)) {
const message = `Cannot apply ALPHA to this type (${type.constructor.name})`;
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, format.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
}
else if (child instanceof nodes_1.TokenNode) {
const token = child.get();
if (token instanceof Tokens.StringTemplate
|| token instanceof Tokens.StringTemplateBegin
|| token instanceof Tokens.StringTemplateMiddle
|| token instanceof Tokens.StringTemplateEnd) {
const issue = this.validateEscapeSequences(token.getStr(), input, child);
if (issue) {
input.issues.push(issue);
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
}
}
}
return ret;
}
static validateEscapeSequences(str, input, node) {
// Valid escape sequences in ABAP string templates: \|, \{, \}, \\, \n, \r, \t
const validEscapes = new Set(["\\|", "\\{", "\\}", "\\\\", "\\n", "\\r", "\\t"]);
for (let i = 0; i < str.length; i++) {
if (str[i] === "\\") {
const escape = str.substring(i, i + 2);
if (!validEscapes.has(escape)) {
return (0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), `Invalid escape sequence "${escape}" in string template`);
}
i++; // skip the next character as it's part of the escape sequence
}
}
return undefined;
}
}
exports.StringTemplate = StringTemplate;
//# sourceMappingURL=string_template.js.map