@abaplint/core
Version:
abaplint - Core API
159 lines • 8.56 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NewObject = void 0;
const basic_1 = require("../../types/basic");
const Expressions = require("../../2_statements/expressions");
const _reference_1 = require("../_reference");
const source_1 = require("./source");
const _object_oriented_1 = require("../_object_oriented");
const method_parameters_1 = require("./method_parameters");
const basic_types_1 = require("../basic_types");
const _type_utils_1 = require("../_type_utils");
const _syntax_input_1 = require("../_syntax_input");
const assert_error_1 = require("../assert_error");
const _typed_identifier_1 = require("../../types/_typed_identifier");
class NewObject {
static runSyntax(node, input, targetType) {
let ret = undefined;
const typeExpr = node.findDirectExpression(Expressions.TypeNameOrInfer);
const typeToken = typeExpr === null || typeExpr === void 0 ? void 0 : typeExpr.getFirstToken();
if (typeToken === undefined) {
throw new Error("NewObject, child TypeNameOrInfer not found");
}
const typeName = typeExpr === null || typeExpr === void 0 ? void 0 : typeExpr.concatTokens();
if (typeName === undefined) {
throw new assert_error_1.AssertError("NewObject, child TypeNameOrInfer not found");
}
else if (typeName === "#" && targetType && targetType instanceof basic_1.ObjectReferenceType) {
const clas = input.scope.findClassDefinition(targetType.getIdentifierName());
if (clas) {
const tid = new _typed_identifier_1.TypedIdentifier(typeToken, input.filename, targetType);
input.scope.addReference(typeToken, tid, _reference_1.ReferenceType.InferredType, input.filename);
input.scope.addReference(typeToken, clas, _reference_1.ReferenceType.ConstructorReference, input.filename, { ooName: clas.getName() });
}
else {
const intf = input.scope.findInterfaceDefinition(targetType.getIdentifierName());
if (intf) {
const message = intf.getName() + " is an interface, cannot be instantiated";
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
}
ret = targetType;
if ((clas === null || clas === void 0 ? void 0 : clas.isAbstract()) === true) {
const message = clas.getName() + " is abstract, cannot be instantiated";
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
}
else if (typeName === "#" && targetType) {
ret = targetType;
}
else if (typeName === "#") {
throw new assert_error_1.AssertError("NewObject, todo, infer type");
}
if (ret === undefined) {
const objDefinition = input.scope.findObjectDefinition(typeName);
if (objDefinition) {
const objref = new basic_1.ObjectReferenceType(objDefinition);
const tid = new _typed_identifier_1.TypedIdentifier(typeToken, input.filename, objref);
input.scope.addReference(typeToken, tid, _reference_1.ReferenceType.InferredType, input.filename);
input.scope.addReference(typeToken, objDefinition, _reference_1.ReferenceType.ObjectOrientedReference, input.filename);
input.scope.addReference(typeToken, objDefinition, _reference_1.ReferenceType.ConstructorReference, input.filename, { ooName: objDefinition.getName() });
const clas = input.scope.findClassDefinition(objref.getIdentifierName());
if ((clas === null || clas === void 0 ? void 0 : clas.isAbstract()) === true) {
const message = clas.getName() + " is abstract, cannot be instantiated";
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
ret = objref;
}
}
if (ret === undefined) {
const basic = new basic_types_1.BasicTypes(input);
const type = basic.resolveTypeName(typeExpr);
if (type instanceof basic_1.UnknownType) {
ret = type;
}
else if (type && !(type instanceof basic_1.VoidType)) {
ret = new basic_1.DataReference(type);
}
else if (type instanceof basic_1.VoidType) {
ret = type;
}
else {
const message = "Type \"" + typeName + "\" not found in scope, NewObject";
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
}
if (ret instanceof basic_1.ObjectReferenceType) {
this.parameters(node, ret, input);
}
else {
for (const s of node.findAllExpressions(Expressions.Source)) {
source_1.Source.runSyntax(s, input, ret);
}
}
if (ret instanceof basic_1.UnknownType && input.scope.getDDIC().inErrorNamespace(typeName) === true) {
const message = "Class or type \"" + typeName + "\" not found";
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
}
return ret;
}
static parameters(node, obj, input) {
const name = obj.getIdentifier().getName();
const def = input.scope.findObjectDefinition(name);
const helper = new _object_oriented_1.ObjectOriented(input.scope);
// eslint-disable-next-line prefer-const
let { method } = helper.searchMethodName(def, "CONSTRUCTOR");
const requiredParameters = (method === null || method === void 0 ? void 0 : method.getParameters().getRequiredParameters()) || [];
const source = node.findDirectExpression(Expressions.Source);
const parameters = node.findDirectExpression(Expressions.ParameterListS);
if (source) {
// single unnamed parameter
const type = this.defaultImportingType(method);
if (type === undefined) {
const message = "NewObject, no default importing parameter found for constructor, " + name;
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return;
}
const sourceType = source_1.Source.runSyntax(source, input, type);
if (new _type_utils_1.TypeUtils(input.scope).isAssignableStrict(sourceType, type) === false) {
const message = `NEW parameter type not compatible`;
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return;
}
}
else if (parameters) {
// parameters with names
if (method === undefined) {
const message = "NewObject, no parameters for constructor found, " + name;
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return;
}
new method_parameters_1.MethodParameters().checkExporting(parameters, input, method);
}
else if (requiredParameters.length > 0) {
const message = `constructor parameter "${requiredParameters[0].getName()}" must be supplied, ` + name;
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
return;
}
}
static defaultImportingType(method) {
let targetType = undefined;
if (method === undefined) {
return undefined;
}
const name = method.getParameters().getDefaultImporting();
for (const i of method.getParameters().getImporting()) {
if (i.getName().toUpperCase() === name) {
targetType = i.getType();
}
}
return targetType;
}
}
exports.NewObject = NewObject;
//# sourceMappingURL=new_object.js.map