All files / src/abap/3_structures structure_parser.ts

100% Statements 68/68
100% Branches 19/19
100% Functions 3/3
100% Lines 68/68

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 681x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 10235x 10235x 10235x 10235x 30570x 30570x 1041x 1041x 29529x 29529x 10235x 10235x 10235x 1x 1x 1x 1x 10235x 10235x 416x 10235x 90x 9819x 4x 9729x 9725x 9725x 9725x 10235x 1x 1x 10235x 10235x 4x 4x 10235x 10235x 10235x 780x 780x 780x 10235x 244x 244x 244x 244x 244x 9211x 9211x 9211x 1x 1x
import {Unknown, Empty, Comment as StatementComment} from "../2_statements/statements/_statement";
import {IStructure} from "./structures/_structure";
import * as Structures from "./structures";
import {Issue} from "../../issue";
import {StructureNode, StatementNode} from "../nodes";
import {Position} from "../../position";
import {IStructureResult} from "./structure_result";
import {IStatementResult} from "../2_statements/statement_result";
import {IFile} from "../../files/_ifile";
import {Severity} from "../../severity";
import {IStructureRunnable} from "./structures/_structure_runnable";
 
export class StructureParser {
  private static readonly singletons: {[index: string]: IStructureRunnable} = {};
 
  public static run(input: IStatementResult): IStructureResult {
    const structure = this.findStructureForFile(input.file.getFilename());
 
    const filtered: StatementNode[] = [];
    for (const s of input.statements) {
      const get = s.get();
      if (get instanceof StatementComment || get instanceof Empty || get instanceof Unknown) {
        continue;
      }
      filtered.push(s);
    }
 
    return this.runFile(structure, input.file, filtered);
  }
 
//////////////////
 
  private static findStructureForFile(filename: string): IStructure {
// todo, not sure this is the right place for this logic
    if (filename.endsWith(".clas.abap")) {
      return new Structures.ClassGlobal();
    } else if (filename.endsWith(".intf.abap")) {
      return new Structures.InterfaceGlobal();
    } else if (filename.match(/\.screen\_\d+\.abap$/i)) {
      return new Structures.DynproLogic();
    } else {
// todo, add a special structure for TYPE-POOLS
      return new Structures.Any();
    }
  }
 
  private static runFile(structure: IStructure, file: IFile, statements: StatementNode[]): {issues: Issue[], node?: StructureNode} {
    const parent = new StructureNode(structure);
    if (this.singletons[structure.constructor.name] === undefined) {
      this.singletons[structure.constructor.name] = structure.getMatcher();
    }
    const result = this.singletons[structure.constructor.name].run(statements, parent);
 
    if (result.error) {
      const issue = Issue.atPosition(file, new Position(1, 1), result.errorDescription, "structure", Severity.Error);
      return {issues: [issue], node: undefined};
    }
    if (result.unmatched.length > 0) {
      const statement = result.unmatched[0];
      const descr = "Unexpected " + statement.get().constructor.name.toUpperCase();
      const issue = Issue.atPosition(file, statement.getStart(), descr, "structure", Severity.Error);
      return {issues: [issue], node: undefined};
    }
 
    return {issues: [], node: parent};
  }
 
}