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