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

81.37% Statements 83/102
81.25% Branches 26/32
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 88x 88x 88x 18x 18x 70x 70x 88x 86x 10x 10x 76x 76x 86x 24x 86x 8x 8x             8x           8x 8x         8x 52x 44x 44x 44x 2x 2x 1x 1x 2x 43x 44x 36x 36x 2x 2x 2x 2x 44x 6x 6x 6x         6x 6x 6x 6x 6x 6x 2x 2x 2x 6x 4x 4x 4x 4x 4x 7x 1x 1x 1x 1x 44x 86x 55x 55x 55x 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 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 new VoidType(CheckSyntaxKey);

          }
        } else if (concat === "=>") {
          if (!(context instanceof ObjectReferenceType)) {
            const message = "ComponentChain, not a reference";
            input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
            return new VoidType(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 new VoidType(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 new VoidType(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 new VoidType(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 new VoidType(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 new VoidType(CheckSyntaxKey);
        }
      }
    }
 
    return context;
  }
 
}