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

88.23% Statements 75/85
86.36% Branches 19/22
100% Functions 1/1
88.23% Lines 75/85

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 851x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 130x 130x 130x 130x 130x 130x 130x 38x 38x 92x 92x 92x 92x 92x 130x 67x 67x 2x 2x 2x 2x 65x 65x 65x 67x 29x 29x 67x 15x 15x     15x 15x 50x 50x 50x 67x 5x 5x 5x 5x 5x 50x 130x 25x 25x 25x 1x 1x 25x         24x 25x 1x 1x 1x 1x 25x         73x 73x 73x 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 {CheckSyntaxKey, SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class AttributeName {
  public 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 new VoidType(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 new VoidType(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 new VoidType(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 new VoidType(CheckSyntaxKey);
      }
    } else {
      const message = "Not an object reference, attribute name";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return new VoidType(CheckSyntaxKey);
    }
 
    return ret;
  }
 
}