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

96.87% Statements 62/64
86.36% Branches 19/22
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 655x 655x 655x 655x 655x 655x 655x 655x 2x 2x 2x 2x 653x 653x 653x 653x 655x 655x 1x 1x 1x 1x 652x 652x 655x 505x 505x 505x 652x 652x 652x 652x 655x 9x 9x 9x 9x 643x 643x 643x 643x 655x 47x 27x 27x 20x 47x     20x 20x 643x 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 || methodDefinition === undefined) {
      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);
    }
  }
}