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 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 4x 4x 4x         4x 52x 48x 48x 51x 52x 52x 9x 9x 9x 1x 1x 1x 1x 9x 50x 52x 9x 9x 52x 10x 10x 50x 50x 50x 50x 8x 50x 42x 42x 50x 50x 52x 46x 45x 45x 1x 1x 50x 50x 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);
    }
 
  }
}