All files / src/abap/5_syntax/statements catch.ts

84.81% Statements 67/79
73.07% Branches 19/26
100% Functions 1/1
84.81% Lines 67/79

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 791x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 15x 15x 15x 16x 16x 16x 16x 7x 16x 9x 9x 9x         16x 16x 1x 1x 1x 1x 15x 15x 14x 14x 15x 15x 15x 4x 4x 4x       4x 4x 4x 4x 4x           15x 4x 4x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 2x 2x 1x 4x 15x 15x 1x
import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {TypedIdentifier, IdentifierMeta} from "../../types/_typed_identifier";
import {UnknownType} from "../../types/basic/unknown_type";
import {ObjectReferenceType, VoidType} from "../../types/basic";
import {Target} from "../expressions/target";
import {IReferenceExtras, ReferenceType} from "../_reference";
import {StatementSyntax} from "../_statement_syntax";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
import {TypeUtils} from "../_type_utils";
 
export class Catch implements StatementSyntax {
  public runSyntax(node: StatementNode, input: SyntaxInput): void {
 
    const names = new Set<string>();
    for (const c of node.findDirectExpressions(Expressions.ClassName)) {
      const token = c.getFirstToken();
      const className = token.getStr().toUpperCase();
      const found = input.scope.existsObject(className);
      if (found?.id) {
        input.scope.addReference(token, found.id, ReferenceType.ObjectOrientedReference, input.filename);
      } else if (input.scope.getDDIC().inErrorNamespace(className) === false) {
        const extra: IReferenceExtras = {ooName: className, ooType: "Void"};
        input.scope.addReference(token, undefined, ReferenceType.ObjectOrientedVoidReference, input.filename, extra);
      } else {
        const message = "CATCH, unknown class " + className;
        input.issues.push(syntaxIssue(input, token, message));
        return;
      }
 
      if (names.has(className)) {
        const message = "Duplicate class name in CATCH: " + className;
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
      names.add(className);
    }
 
    const target = node.findDirectExpression(Expressions.Target);
    const firstClassName = node.findDirectExpression(Expressions.ClassName)?.getFirstToken().getStr();
 
    if (target?.findDirectExpression(Expressions.InlineData)) {
      const token = target.findFirstExpression(Expressions.TargetField)?.getFirstToken();
      const found = input.scope.existsObject(firstClassName);
      if (token && firstClassName && found?.id) {
        const identifier = new TypedIdentifier(token, input.filename, new ObjectReferenceType(found.id), [IdentifierMeta.InlineDefinition]);
        input.scope.addIdentifier(identifier);
        input.scope.addReference(token, identifier, ReferenceType.DataWriteReference, input.filename);
      } else if (token && input.scope.getDDIC().inErrorNamespace(firstClassName) === false) {
        const identifier = new TypedIdentifier(token, input.filename, VoidType.get(firstClassName), [IdentifierMeta.InlineDefinition]);
        input.scope.addIdentifier(identifier);
        input.scope.addReference(token, identifier, ReferenceType.DataWriteReference, input.filename);
      } else if (token) {
        const message = "Catch, could not determine type for \"" + token.getStr() + "\"";
        const identifier = new TypedIdentifier(token, input.filename, new UnknownType(message), [IdentifierMeta.InlineDefinition]);
        input.scope.addIdentifier(identifier);
        input.scope.addReference(token, identifier, ReferenceType.DataWriteReference, input.filename);
      }
    } else if (target) {
      const targetType = Target.runSyntax(target, input);
      if (targetType instanceof ObjectReferenceType) {
        for (const c of node.findDirectExpressions(Expressions.ClassName)) {
          const token = c.getFirstToken();
          const className = token.getStr().toUpperCase();
          const found = input.scope.existsObject(className);
          if (found?.id) {
            const catchType = new ObjectReferenceType(found.id);
            if (new TypeUtils(input.scope).isAssignableStrict(catchType, targetType) === false) {
              const message = "CATCH target not compatible with " + className;
              input.issues.push(syntaxIssue(input, token, message));
              return;
            }
          }
        }
      }
    }
 
  }
}