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

94.36% Statements 67/71
65.85% Branches 27/41
100% Functions 1/1
94.36% Lines 67/71

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 711x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 4x 4x 4x         4x 38x 34x 34x 37x 38x 38x 9x 9x 9x 1x 1x 1x 1x 9x 36x 38x 9x 9x 38x 10x 10x 36x 36x 36x 36x 8x 36x 28x 28x 36x 36x 38x 32x 31x 31x 1x 1x 36x 36x 1x
import * as Expressions from "../../2_statements/expressions";
import {ExpressionNode, StatementNode} from "../../nodes";
import {Source} from "../expressions/source";
import {FSTarget} from "../expressions/fstarget";
import {AnyType, CharacterType, VoidType} from "../../types/basic";
import {StatementSyntax} from "../_statement_syntax";
import {AbstractType} from "../../types/basic/_abstract_type";
import {Dynamic} from "../expressions/dynamic";
import {TypeUtils} from "../_type_utils";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class Assign implements StatementSyntax {
  public runSyntax(node: StatementNode, input: SyntaxInput): void {
    const assignSource = node.findDirectExpression(Expressions.AssignSource);
    const isComponent = assignSource?.getFirstChild()?.concatTokens().toUpperCase() === "COMPONENT";
    const sources: ExpressionNode[] = assignSource?.findDirectExpressionsMulti([Expressions.Source, Expressions.SimpleSource3]) || [];
    const theSource = sources[sources.length - 1];
 
    let sourceType: AbstractType | undefined = undefined;
    const firstAssign = assignSource?.getChildren()[0];
    const secondAssign = assignSource?.getChildren()[1];
    const thirdAssign = assignSource?.getChildren()[2];
    if (secondAssign?.concatTokens() === "=>" && firstAssign && thirdAssign?.get() instanceof Expressions.Dynamic) {
      const name = firstAssign.concatTokens();
      const found = input.scope.findClassDefinition(name) || input.scope.findVariable(name);
      if (found === undefined && input.scope.getDDIC().inErrorNamespace(name) && name.startsWith("(") === false) {
        const message = name + " not found, dynamic";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
      sourceType = VoidType.get("Dynamic");
    } else {
      sourceType = Source.runSyntax(theSource, input, undefined, false, isComponent === false);
    }
 
    if (assignSource?.getChildren().length === 5
        && isComponent) {
      const componentSource = sources[sources.length - 2];
      const componentType = Source.runSyntax(componentSource, input);
      if (new TypeUtils(input.scope).isAssignable(componentType, new CharacterType(30)) === false) {
        const message = "component name must be charlike";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
    }
 
    if (sourceType === undefined || assignSource?.findDirectExpression(Expressions.Dynamic)) {
      sourceType = AnyType.get();
    }
    for (const d of assignSource?.findAllExpressions(Expressions.Dynamic) || []) {
      Dynamic.runSyntax(d, input);
    }
 
    const target = node.findDirectExpression(Expressions.FSTarget);
    if (target) {
      if (isComponent) {
        FSTarget.runSyntax(target, input, AnyType.get());
      } else {
        FSTarget.runSyntax(target, input, sourceType);
      }
    }
 
    for (const s of node.findAllExpressions(Expressions.Source)) {
      if (s === theSource) {
        continue;
      }
      Source.runSyntax(s, input);
    }
 
  }
}