UNPKG

@abaplint/core

Version:
199 lines 7.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IncludeGraph = void 0; const statements_1 = require("../abap/2_statements/statements"); const expressions_1 = require("../abap/2_statements/expressions"); const objects_1 = require("../objects"); const check_include_1 = require("../rules/check_include"); const position_1 = require("../position"); const issue_1 = require("../issue"); const _abap_object_1 = require("../objects/_abap_object"); const severity_1 = require("../severity"); // todo, check for cycles/circular dependencies, method findTop // todo, add configurable error for multiple use includes function getABAPObjects(reg) { const ret = []; for (const o of reg.getObjects()) { if (o instanceof _abap_object_1.ABAPObject) { ret.push(o); } } return ret; } class Graph { constructor() { this.vertices = []; this.edges = []; } addVertex(vertex) { this.vertices.push(vertex); } findInclude(includeName) { for (const v of this.vertices) { if (v.includeName.toUpperCase() === includeName.toUpperCase()) { return v; } } return undefined; } findVertex(filename) { for (const v of this.vertices) { if (v.filename.toUpperCase() === filename.toUpperCase()) { return v; } } return undefined; } addEdge(from, toFilename) { this.edges.push({ from: from.filename, to: toFilename }); } findTop(filename) { const ret = []; for (const e of this.edges) { if (e.from === filename) { ret.push(...this.findTop(e.to)); } } if (ret.length === 0) { const found = this.findVertex(filename); if (found !== undefined) { ret.push(found); } } return ret; } } class IncludeGraph { constructor(reg) { this.reg = reg; this.issues = []; this.graph = new Graph(); this.build(); } getIssues() { return this.issues; } listMainForInclude(filename) { const ret = []; if (filename === undefined) { return []; } for (const f of this.graph.findTop(filename)) { if (f.include === false) { ret.push(f.filename); } } return ret; } getIssuesFile(file) { const ret = []; for (const i of this.issues) { if (i.getFilename() === file.getFilename()) { ret.push(i); } } return ret; } /////////////////////////////// build() { this.addVertices(); for (const o of getABAPObjects(this.reg)) { for (const f of o.getABAPFiles()) { for (const s of f.getStatements()) { if (s.get() instanceof statements_1.Include) { const ifFound = s.concatTokens().toUpperCase().includes("IF FOUND"); const iexp = s.findFirstExpression(expressions_1.IncludeName); if (iexp === undefined) { throw new Error("unexpected Include node"); } const name = iexp.getFirstToken().getStr().toUpperCase(); if (name.match(/^(\/\w+\/)?L.+XX$/)) { // function module XX includes, possibily namespaced continue; } const found = this.graph.findInclude(name); if (found === undefined) { if (ifFound === false) { const issue = issue_1.Issue.atStatement(f, s, "Include " + name + " not found", new check_include_1.CheckInclude().getMetadata().key, severity_1.Severity.Error); this.issues.push(issue); } } else if (found.include === false) { const issue = issue_1.Issue.atStatement(f, s, "Not possible to INCLUDE a main program, " + name, new check_include_1.CheckInclude().getMetadata().key, severity_1.Severity.Error); this.issues.push(issue); } else { this.graph.addEdge(found, f.getFilename()); } } } } } this.findUnusedIncludes(); } findUnusedIncludes() { for (const v of this.graph.vertices) { if (v.include === true) { if (this.listMainForInclude(v.filename).length === 0) { const f = this.reg.getFileByName(v.filename); if (f === undefined) { throw new Error("findUnusedIncludes internal error"); } const issue = issue_1.Issue.atPosition(f, new position_1.Position(1, 1), "INCLUDE not used anywhere", new check_include_1.CheckInclude().getMetadata().key, severity_1.Severity.Error); this.issues.push(issue); } } } } addVertices() { for (const o of getABAPObjects(this.reg)) { if (o instanceof objects_1.Program) { const file = o.getMainABAPFile(); if (file) { this.graph.addVertex({ filename: file.getFilename(), includeName: o.getName(), include: o.isInclude() }); } } else if (o instanceof objects_1.TypePool) { const file = o.getMainABAPFile(); if (file) { this.graph.addVertex({ filename: file.getFilename(), includeName: o.getName(), include: false }); } } else if (o instanceof objects_1.Class) { for (const f of o.getSequencedFiles()) { this.graph.addVertex({ filename: f.getFilename(), includeName: o.getName(), include: false }); } } else if (o instanceof objects_1.FunctionGroup) { for (const i of o.getIncludeFiles()) { this.graph.addVertex({ filename: i.file.getFilename(), includeName: i.name, include: true }); } const file = o.getMainABAPFile(); if (file) { this.graph.addVertex({ filename: file.getFilename(), includeName: o.getName(), include: false }); } } } } } exports.IncludeGraph = IncludeGraph; //# sourceMappingURL=include_graph.js.map