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 96 971x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 393x 393x 393x 393x 393x 393x 393x 40x 40x 353x 353x 353x 353x 353x 393x 326x 326x 2x 2x 2x 2x 324x 324x 324x 326x 60x 60x 326x 36x 36x     36x 36x 326x 287x 287x 287x 9x 9x 9x 9x 287x 278x 278x 278x 326x 14x 14x 14x 14x 14x 278x 393x 27x 27x 27x 1x 1x 27x         26x 27x 1x 1x 1x 1x 27x         303x 303x 303x 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;
 
    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;
  }
 
}