UNPKG

@abaplint/core

Version:
260 lines • 12.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MethodParameters = void 0; const basic_1 = require("../../types/basic"); const Expressions = require("../../2_statements/expressions"); const nodes_1 = require("../../nodes"); const inline_data_1 = require("./inline_data"); const target_1 = require("./target"); const source_1 = require("./source"); const _type_utils_1 = require("../_type_utils"); const _syntax_input_1 = require("../_syntax_input"); const assert_error_1 = require("../assert_error"); const field_chain_1 = require("./field_chain"); const _reference_1 = require("../_reference"); class MethodParameters { constructor() { this.requiredParameters = undefined; } runSyntax(node, input, method) { var _a; if (!(node.get() instanceof Expressions.MethodParameters)) { throw new assert_error_1.AssertError("MethodParameters, unexpected input"); } const children = node.getChildren().slice(); if (method instanceof basic_1.VoidType) { this.requiredParameters = new Set(); } else { this.requiredParameters = new Set(method.getParameters().getRequiredParameters().map(i => i.getName().toUpperCase())); } while (children.length > 0) { const name = (_a = children.shift()) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr().toUpperCase(); switch (name) { case "EXPORTING": this.checkExporting(children.shift(), input, method, false); break; case "IMPORTING": this.checkImporting(children.shift(), input, method); break; case "CHANGING": this.checkChanging(children.shift(), input, method); break; case "RECEIVING": this.checkReceiving(children.shift(), input, method); break; case "EXCEPTIONS": { // todo, old style exceptions const node = children.shift(); const exceptions = node.findFirstExpression(Expressions.ParameterException); for (const s of (exceptions === null || exceptions === void 0 ? void 0 : exceptions.findAllExpressions(Expressions.SimpleFieldChain)) || []) { field_chain_1.FieldChain.runSyntax(s, input, _reference_1.ReferenceType.DataReadReference); } } break; default: throw new assert_error_1.AssertError("MethodParameters, unexpected token, " + name); } } this.reportErrors(node, input); } /////////////////////// checkReceiving(node, input, method) { var _a; const type = method instanceof basic_1.VoidType ? method : (_a = method.getParameters().getReturning()) === null || _a === void 0 ? void 0 : _a.getType(); if (type === undefined) { const message = "Method does not have a returning parameter"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } else if (!(node instanceof nodes_1.ExpressionNode)) { const message = "checkReceiving, not an expression node"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } const target = node.findDirectExpression(Expressions.Target); const inline = target === null || target === void 0 ? void 0 : target.findDirectExpression(Expressions.InlineData); if (inline) { inline_data_1.InlineData.runSyntax(inline, input, type); } else if (target) { const targetType = target_1.Target.runSyntax(target, input); if (targetType && new _type_utils_1.TypeUtils(input.scope).isAssignable(type, targetType) === false) { const message = "Method returning value not type compatible"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } } } checkImporting(node, input, method) { for (const item of this.parameterListT(node, input)) { let parameterType = undefined; if (method instanceof basic_1.VoidType) { parameterType = method; } else { const parameter = method.getParameters().getExporting().find(p => p.getName().toUpperCase() === item.name); if (parameter === undefined) { const message = "Method exporting parameter \"" + item.name + "\" does not exist"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } parameterType = parameter.getType(); } const inline = item.target.findDirectExpression(Expressions.InlineData); if (inline) { inline_data_1.InlineData.runSyntax(inline, input, parameterType); } else if (item.targetType === undefined) { const message = "Could not determine target type"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } else if (item.targetType && new _type_utils_1.TypeUtils(input.scope).isAssignable(parameterType, item.targetType) === false) { const message = "Method parameter type not compatible, " + item.name; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } } } checkChanging(node, input, method) { var _a; for (const item of this.parameterListT(node, input)) { if (item.target.findFirstExpression(Expressions.InlineData) !== undefined) { const message = "CHANGING cannot be inlined"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } let parameterType = undefined; if (method instanceof basic_1.VoidType) { parameterType = method; } else { const parameter = method.getParameters().getChanging().find(p => p.getName().toUpperCase() === item.name); if (parameter === undefined) { const message = "Method changing parameter \"" + item.name + "\" does not exist"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } parameterType = parameter.getType(); } if (item.targetType && new _type_utils_1.TypeUtils(input.scope).isAssignable(parameterType, item.targetType) === false) { const message = "Method parameter type not compatible, " + item.name; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } (_a = this.requiredParameters) === null || _a === void 0 ? void 0 : _a.delete(item.name); } } checkExporting(node, input, method, errors = true) { const items = this.parameterListS(node, input, method); if (method instanceof basic_1.VoidType) { return; } const allImporting = method.getParameters().getImporting(); if (this.requiredParameters === undefined) { this.requiredParameters = new Set(method.getParameters().getRequiredParameters().map(i => i.getName().toUpperCase())); } for (const item of items) { const parameter = allImporting.find(p => p.getName().toUpperCase() === item.name); if (parameter === undefined) { const message = "Method importing parameter \"" + item.name + "\" does not exist"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); continue; } else if (new _type_utils_1.TypeUtils(input.scope).isAssignableStrict(item.sourceType, parameter.getType(), item.source) === false) { const message = "Method parameter type not compatible, " + item.name; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); return; } this.requiredParameters.delete(item.name); } if (errors === true) { this.reportErrors(node, input); } } reportErrors(node, input) { var _a; for (const r of ((_a = this.requiredParameters) === null || _a === void 0 ? void 0 : _a.values()) || []) { const message = `method parameter "${r}" must be supplied`; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); } } parameterListS(node, input, method) { var _a; if (node === undefined) { return []; } else if (!(node.get() instanceof Expressions.ParameterListS)) { throw new assert_error_1.AssertError("parameterListS, unexpected node"); } const ret = []; for (const c of node.getChildren()) { if (!(c.get() instanceof Expressions.ParameterS) || !(c instanceof nodes_1.ExpressionNode)) { throw new assert_error_1.AssertError("parameterListS, unexpected node, child"); } const name = (_a = c.findDirectExpression(Expressions.ParameterName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr().toUpperCase(); if (name === undefined) { throw new assert_error_1.AssertError("parameterListS, no name determined"); } const source = c.findDirectExpression(Expressions.Source); if (source === undefined) { throw new assert_error_1.AssertError("parameterListS, no source found"); } let targetType = undefined; if (!(method instanceof basic_1.VoidType)) { for (const i of method.getParameters().getImporting()) { if (i.getName().toUpperCase() === name) { targetType = i.getType(); break; } } } else { targetType = method; } let sourceType = source_1.Source.runSyntax(source, input, targetType); if (sourceType === undefined) { if (method instanceof basic_1.VoidType) { sourceType = method; } else { const message = "No source type determined for parameter " + name + " input"; input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message)); sourceType = basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey); } } ret.push({ name, source, sourceType }); } return ret; } parameterListT(node, input) { var _a; if (node === undefined) { return []; } else if (!(node.get() instanceof Expressions.ParameterListT)) { throw new assert_error_1.AssertError("parameterListT, unexpected node"); } const ret = []; for (const c of node.getChildren()) { if (!(c.get() instanceof Expressions.ParameterT) || !(c instanceof nodes_1.ExpressionNode)) { throw new assert_error_1.AssertError("parameterListT, unexpected node, child"); } const name = (_a = c.findDirectExpression(Expressions.ParameterName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr().toUpperCase(); if (name === undefined) { throw new assert_error_1.AssertError("parameterListT, no name determined"); } const target = c.findDirectExpression(Expressions.Target); if (target === undefined) { throw new assert_error_1.AssertError("parameterListT, no target found"); } const targetType = target_1.Target.runSyntax(target, input); ret.push({ name, target, targetType }); } return ret; } } exports.MethodParameters = MethodParameters; //# sourceMappingURL=method_parameters.js.map