@abaplint/core
Version:
abaplint - Core API
191 lines • 10.8 kB
JavaScript
;
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