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

89.58% Statements 86/96
88.46% Branches 23/26
100% Functions 1/1
89.58% Lines 86/96

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 961x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 164x 164x 164x 164x 164x 164x 164x 40x 40x 124x 124x 124x 124x 124x 164x 99x 99x 2x 2x 2x 2x 97x 97x 97x 99x 35x 35x 99x 20x 20x     20x 20x 99x 76x 76x 76x 9x 9x 9x 9x 76x 67x 67x 67x 99x 6x 6x 6x 6x 6x 67x 164x 25x 25x 25x 1x 1x 25x         24x 25x 1x 1x 1x 1x 25x         90x 90x 90x 1x 1x
import {INode} from "../../nodes/_inode";
import {AbstractType} from "../../types/basic/_abstract_type";
import {VoidType} from "../../types/basic/void_type";
import {StructureType} from "../../types/basic/structure_type";
import {ObjectReferenceType} from "../../types/basic/object_reference_type";
import {ObjectOriented} from "../_object_oriented";
import {DataReference} from "../../types/basic/data_reference_type";
import {ReferenceType} from "../_reference";
import {TypedIdentifier} from "../../types/_typed_identifier";
import {AnyType} from "../../types/basic";
import {ClassAttribute} from "../../types/class_attribute";
import {ClassConstant} from "../../types/class_constant";
import {CheckSyntaxKey, SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class AttributeName {
  public static runSyntax(
    context: AbstractType | undefined,
    node: INode,
    input: SyntaxInput,
    type?: ReferenceType | ReferenceType[] | undefined,
    error = true): AbstractType | undefined {
 
    if (context instanceof VoidType) {
      return context;
    }
 
    const helper = new ObjectOriented(input.scope);
 
    let ret: AbstractType | undefined = undefined;
 
    if (context instanceof ObjectReferenceType) {
      const def = input.scope.findObjectDefinition(context.getIdentifierName());
      if (def === undefined) {
        const message = "Definition for \"" + context.getIdentifierName() + "\" not found in scope(AttributeName)";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return VoidType.get(CheckSyntaxKey);
      }
      const token = node.getFirstToken();
      const name = token.getStr();
      let found: TypedIdentifier | undefined = helper.searchAttributeName(def, name);
      if (found === undefined) {
        found = helper.searchConstantName(def, name);
      }
      if (found === undefined) {
        const message = "Attribute or constant \"" + name + "\" not found in \"" + def.getName() + "\"";
        if (error === true) {
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        }
        return VoidType.get(CheckSyntaxKey);
      }
      if (found instanceof ClassAttribute || found instanceof ClassConstant) {
        const owner = helper.findAttributeOwner(def, found);
        const notVisible = helper.memberNotVisible(found.getVisibility(), def, owner, input.scope.getEnclosingClassName());
        if (notVisible !== undefined) {
          const message = `Attribute "${name}" is ${notVisible} and cannot be accessed`;
          input.issues.push(syntaxIssue(input, token, message));
          return VoidType.get(CheckSyntaxKey);
        }
      }
      if (type) {
        input.scope.addReference(token, found, type, input.filename);
      }
      if (found && name.includes("~")) {
        const idef = input.scope.findInterfaceDefinition(name.split("~")[0]);
        if (idef) {
          input.scope.addReference(token, idef, ReferenceType.ObjectOrientedReference, input.filename);
        }
      }
      ret = found.getType();
    } else if (context instanceof DataReference) {
      const sub = context.getType();
      const name = node.getFirstToken().getStr();
      if (name === "*" || sub instanceof VoidType || sub instanceof AnyType) {
        return sub;
      }
      if (!(sub instanceof StructureType)) {
        const message = "Data reference not structured";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return VoidType.get(CheckSyntaxKey);
      }
      ret = sub.getComponentByName(name);
      if (ret === undefined) {
        const message = "Component \"" + name + "\" not found in data reference structure";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return VoidType.get(CheckSyntaxKey);
      }
    } else {
      const message = "Not an object reference, attribute name";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return VoidType.get(CheckSyntaxKey);
    }
 
    return ret;
  }
 
}