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

77.27% Statements 85/110
77.14% Branches 27/35
100% Functions 1/1
77.27% Lines 85/110

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 102 103 104 105 106 107 108 109 1101x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 176x 176x 176x 19x 19x 157x 157x 176x 174x 25x 25x 149x 149x 174x 46x 174x 1x         1x 1x 103x 8x 8x             8x           8x 8x         8x 102x 92x 92x 92x 1x 1x     1x 92x 92x 84x 84x 5x 5x 5x 5x 92x 7x 7x 7x         7x 7x 7x 7x 7x 7x 2x 2x 2x 7x 5x 5x 5x 5x 5x 8x 1x 1x 1x 1x 92x 174x 124x 124x 124x 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.Dereference) {
        if (!(context instanceof DataReference)) {
          const message = "Not a data reference, cannot be dereferenced";
          input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
          return VoidType.get(CheckSyntaxKey);
        }
        context = context.getType();
        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;
  }
 
}