All files / src/abap/5_syntax/expressions component_chain.ts

81.37% Statements 83/102
80.64% Branches 25/31
100% Functions 1/1
81.37% Lines 83/102

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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 1021x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 139x 139x 139x 18x 18x 121x 121x 139x 139x 24x 24x 115x 115x 139x 36x 139x 9x 9x             9x           9x 9x         9x 79x 70x 70x 70x 2x 2x 1x 1x 2x 69x 70x 61x 61x 5x 5x 5x 5x 70x 7x 7x 7x         7x 7x 7x 7x 7x 7x 2x 2x 2x 7x 5x 5x 5x 5x 5x 8x 1x 1x 1x 1x 70x 139x 89x 89x 89x 1x 1x
import * as Expressions from "../../2_statements/expressions";
import {AbstractType} from "../../types/basic/_abstract_type";
import {VoidType} from "../../types/basic/void_type";
import {StructureType} from "../../types/basic/structure_type";
import {ExpressionNode} from "../../nodes";
import {DataReference, ObjectReferenceType, UnknownType} from "../../types/basic";
import {ClassDefinition} from "../../types";
import {IReferenceExtras, ReferenceType} from "../_reference";
import {ObjectOriented} from "../_object_oriented";
import {CheckSyntaxKey, SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class ComponentChain {
  public static runSyntax(context: AbstractType | undefined, node: ExpressionNode,
                          input: SyntaxInput): AbstractType | undefined {
 
    if (context === undefined) {
      return undefined;
    }
 
    const children = node.getChildren();
    for (let i = 0; i < children.length; i++) {
      if (context instanceof VoidType || context instanceof UnknownType) {
        return context;
      }
 
      const child = children[i];
      if (i === 0 && child.concatTokens().toUpperCase() === "TABLE_LINE") {
        continue;
      } else if (child.get() instanceof Expressions.ArrowOrDash) {
        const concat = child.concatTokens();
        if (concat === "-") {
          if (!(context instanceof StructureType)) {
            const message = "ComponentChain, not a structure";
            input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
            return VoidType.get(CheckSyntaxKey);

          }
        } else if (concat === "=>") {
          if (!(context instanceof ObjectReferenceType)) {
            const message = "ComponentChain, not a reference";
            input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
            return VoidType.get(CheckSyntaxKey);
          }
        } else if (concat === "->") {
          if (!(context instanceof ObjectReferenceType) && !(context instanceof DataReference)) {
            const message = "ComponentChain, not a reference";
            input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
            return VoidType.get(CheckSyntaxKey);
          }
        }
      } else if (child.get() instanceof Expressions.ComponentName) {
        const name = child.concatTokens();
 
        if (context instanceof DataReference) {
          context = context.getType();
          if (name === "*") {
            continue;
          }
        }
 
        if (context instanceof StructureType) {
          context = context.getComponentByName(name);
          if (context === undefined) {
            const message = "Component \"" + name + "\" not found in structure";
            input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
            return VoidType.get(CheckSyntaxKey);
          }
        } else if (context instanceof ObjectReferenceType) {
          const id = context.getIdentifier();
          const def = input.scope.findObjectDefinition(id.getName());
          if (def === undefined) {
            const message = id.getName() + " not found in scope";
            input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
            return VoidType.get(CheckSyntaxKey);
          }
 
          const helper = new ObjectOriented(input.scope);
          const found = helper.searchAttributeName(def, name);
 
          context = found?.getType();
          if (context === undefined) {
            const message = "Attribute \"" + name + "\" not found";
            input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
            return VoidType.get(CheckSyntaxKey);
          } else {
            const extra: IReferenceExtras = {
              ooName: id.getName(),
              ooType: id instanceof ClassDefinition ? "CLAS" : "INTF"};
            input.scope.addReference(child.getFirstToken(), found, ReferenceType.DataWriteReference, input.filename, extra);
          }
        } else {
          const message = "ComponentChain, not a structure, " + context?.constructor.name;
          input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
          return VoidType.get(CheckSyntaxKey);
        }
      }
    }
 
    return context;
  }
 
}