UNPKG

@abaplint/core

Version:
159 lines • 8.56 kB
"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