UNPKG

@abaplint/core

Version:
191 lines • 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FieldChain = void 0; const nodes_1 = require("../../nodes"); const Expressions = require("../../2_statements/expressions"); const tokens_1 = require("../../1_lexer/tokens"); const basic_1 = require("../../types/basic"); const component_name_1 = require("./component_name"); const attribute_name_1 = require("./attribute_name"); const _reference_1 = require("../_reference"); const field_offset_1 = require("./field_offset"); const field_length_1 = require("./field_length"); const table_expression_1 = require("./table_expression"); const expressions_1 = require("../../2_statements/expressions"); const dereference_1 = require("./dereference"); const source_field_symbol_1 = require("./source_field_symbol"); const source_field_1 = require("./source_field"); const _syntax_input_1 = require("../_syntax_input"); const version_1 = require("../../../version"); class FieldChain { static runSyntax(node, input, refType, allowGenericDeference = false) { var _a, _b, _c; if (((_a = node.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.SourceField && node.findDirectExpression(Expressions.ComponentName)) { // workaround for names with dashes, eg. "sy-repid" const concat = node.concatTokens(); const offset = ((_b = node.findDirectExpression(Expressions.FieldOffset)) === null || _b === void 0 ? void 0 : _b.concatTokens()) || ""; const length = ((_c = node.findDirectExpression(Expressions.FieldLength)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || ""; const found = input.scope.findVariable(concat.replace(offset, "").replace(length, "")); if (found) { if (refType) { input.scope.addReference(node.getFirstToken(), found, refType, input.filename); } // this is not completely correct, but will work, dashes in names is a mess anyhow return found.getType(); } } let context = undefined; const children = node.getChildren(); context = this.findTop(children[0], input, refType); for (let i = 1; i < children.length; i++) { const current = children[i]; if (current === undefined) { break; } if (current.get() instanceof tokens_1.DashW) { const message = "Ending with dash"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, current.getFirstToken(), message)); return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } else if (current.get() instanceof tokens_1.Dash) { if (context instanceof basic_1.UnknownType) { const message = "Not a structure, type unknown, FieldChain"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, current.getFirstToken(), message)); return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } else if (!(context instanceof basic_1.StructureType) && !(context instanceof basic_1.TableType && context.isWithHeader()) && !(context instanceof basic_1.VoidType)) { if (context instanceof basic_1.TableType && context.isWithHeader() === false) { let contextName = ""; for (let j = 0; j < i; j++) { contextName += children[j].concatTokens(); } if (input.scope.isAllowHeaderUse(contextName)) { // FOR ALL ENTRIES workaround context = context.getRowType(); if (!(context instanceof basic_1.StructureType) && !(context instanceof basic_1.VoidType)) { context = new basic_1.StructureType([{ name: "TABLE_LINE", type: context }]); } } else { const message = "Table without header, cannot access fields, " + contextName; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, current.getFirstToken(), message)); return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } } else { const message = "Not a structure, FieldChain, " + (context === null || context === void 0 ? void 0 : context.constructor.name) + ", " + current.concatTokens(); input.issues.push((0, _syntax_input_1.syntaxIssue)(input, current.getFirstToken(), message)); return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } } } else if (current.get() instanceof tokens_1.InstanceArrow) { if (!(context instanceof basic_1.ObjectReferenceType) && !(context instanceof basic_1.DataReference) && !(context instanceof basic_1.VoidType)) { const message = "Not an object reference, field chain"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, current.getFirstToken(), message)); return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } } else if (current.get() instanceof expressions_1.Dereference) { context = dereference_1.Dereference.runSyntax(current, context, input); if (allowGenericDeference === false && (context === null || context === void 0 ? void 0 : context.isGeneric()) === true && input.scope.getVersion() < version_1.Version.v756 && input.scope.getVersion() !== version_1.Version.Cloud) { throw new Error("A generic reference cannot be dereferenced"); } } else if (current.get() instanceof Expressions.ComponentName) { if (context instanceof basic_1.TableType && context.isWithHeader()) { context = context.getRowType(); } context = component_name_1.ComponentName.runSyntax(context, current, input); } else if (current instanceof nodes_1.ExpressionNode && current.get() instanceof Expressions.TableExpression) { if (!(context instanceof basic_1.TableType) && !(context instanceof basic_1.VoidType)) { const message = "Table expression, expected table"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, current.getFirstToken(), message)); return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } table_expression_1.TableExpression.runSyntax(current, input, context); if (!(context instanceof basic_1.VoidType)) { context = context.getRowType(); } } else if (current.get() instanceof Expressions.AttributeName) { context = attribute_name_1.AttributeName.runSyntax(context, current, input, refType); } else if (current.get() instanceof Expressions.FieldOffset && current instanceof nodes_1.ExpressionNode) { const offset = field_offset_1.FieldOffset.runSyntax(current, input); if (offset) { if (context instanceof basic_1.CharacterType) { context = new basic_1.CharacterType(context.getLength() - offset); } else if (context instanceof basic_1.HexType) { context = new basic_1.HexType(context.getLength() - offset); } } } else if (current.get() instanceof Expressions.FieldLength && current instanceof nodes_1.ExpressionNode) { const length = field_length_1.FieldLength.runSyntax(current, input); if (length) { if (context instanceof basic_1.CharacterType) { context = new basic_1.CharacterType(length); } else if (context instanceof basic_1.HexType) { context = new basic_1.HexType(length); } } } } return context; } //////////////// static findTop(node, input, type) { if (node === undefined) { return undefined; } if (node instanceof nodes_1.ExpressionNode && node.get() instanceof Expressions.SourceFieldSymbol) { return source_field_symbol_1.SourceFieldSymbol.runSyntax(node, input); } else if (node instanceof nodes_1.ExpressionNode && node.get() instanceof Expressions.SourceField) { return source_field_1.SourceField.runSyntax(node, input, type); } else if (node instanceof nodes_1.ExpressionNode && node.get() instanceof Expressions.Field) { return source_field_1.SourceField.runSyntax(node, input, type); } else if (node.get() instanceof Expressions.ClassName) { const classTok = node.getFirstToken(); const classNam = classTok.getStr(); if (classNam.toUpperCase() === "OBJECT") { return new basic_1.GenericObjectReferenceType(); } const found = input.scope.existsObject(classNam); if (found === null || found === void 0 ? void 0 : found.id) { input.scope.addReference(classTok, found.id, _reference_1.ReferenceType.ObjectOrientedReference, input.filename); return new basic_1.ObjectReferenceType(found.id); } else if (input.scope.getDDIC().inErrorNamespace(classNam) === false) { input.scope.addReference(classTok, undefined, _reference_1.ReferenceType.ObjectOrientedVoidReference, input.filename, { ooName: classNam.toUpperCase() }); return basic_1.VoidType.get(classNam); } else { const message = "Unknown class " + classNam; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } } return undefined; } } exports.FieldChain = FieldChain; //# sourceMappingURL=field_chain.js.map