All files / src/abap/5_syntax/statements method_implementation.ts

96.87% Statements 62/64
85.71% Branches 18/21
100% Functions 1/1
96.87% Lines 62/64

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 641x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 492x 492x 492x 492x 492x 492x 492x 492x 2x 2x 2x 2x 490x 490x 490x 490x 492x 492x 1x 1x 1x 1x 489x 489x 492x 374x 374x 374x 489x 489x 489x 489x 492x 7x 7x 7x 7x 482x 482x 482x 482x 492x 42x 23x 23x 19x 42x     19x 19x 482x 1x
import {StatementNode} from "../../nodes";
import * as Expressions from "../../2_statements/expressions";
import {ObjectOriented} from "../_object_oriented";
import {ScopeType} from "../_scope_type";
import {ReferenceType} from "../_reference";
import {StatementSyntax} from "../_statement_syntax";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
import {Visibility} from "../../4_file_information/visibility";
 
export class MethodImplementation implements StatementSyntax {
  public runSyntax(node: StatementNode, input: SyntaxInput): void {
    const helper = new ObjectOriented(input.scope);
 
    const className = input.scope.getName();
    const methodToken = node.findFirstExpression(Expressions.MethodName)!.getFirstToken();
    const methodName = methodToken?.getStr();
 
    const classDefinition = input.scope.findClassDefinition(className);
    if (classDefinition === undefined) {
      const message = "Class definition for \"" + className + "\" not found";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
 
    const {method: methodDefinition} = helper.searchMethodName(classDefinition, methodName);
 
    if (classDefinition.isForTesting()
        && methodDefinition?.getVisibility() !== Visibility.Private
        && ["SETUP", "TEARDOWN", "CLASS_SETUP", "CLASS_TEARDOWN"].includes(methodName.toUpperCase())) {
      const message = "Special test method \"" + methodName + "\" must be private";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
 
    const start = node.getFirstToken().getStart();
    if (methodDefinition?.isStatic() === false) {
      input.scope.push(ScopeType.MethodInstance, methodName, start, input.filename);
      input.scope.addList(classDefinition.getAttributes().getInstance());
    }
 
    input.scope.push(ScopeType.Method, methodName, start, input.filename);
 
    // note: the scope must be pushed before returning
    if (methodDefinition === undefined) {
      const message = "Method definition \"" + methodName + "\" not found";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
 
    input.scope.addReference(methodToken, methodDefinition, ReferenceType.MethodImplementationReference, input.filename);
    input.scope.addList(methodDefinition.getParameters().getAll());
 
    for (const i of helper.findInterfaces(classDefinition)) {
      if (methodName.toUpperCase().startsWith(i.name.toUpperCase() + "~") === false) {
        continue;
      }
      const idef = input.scope.findInterfaceDefinition(i.name);
      if (idef === undefined) {
        continue;
      }
      input.scope.addReference(methodToken, idef, ReferenceType.ObjectOrientedReference, input.filename);
    }
  }
}