UNPKG

@abaplint/core

Version:
240 lines • 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Indent = void 0; const Statements = require("../abap/2_statements/statements"); const Expressions = require("../abap/2_statements/expressions"); const _statement_1 = require("../abap/2_statements/statements/_statement"); const virtual_position_1 = require("../virtual_position"); const structures_1 = require("../abap/3_structures/structures"); // todo, will break if there is multiple statements per line? class Indent { constructor(options) { this.globalClasses = new Set(); this.options = options || {}; } execute(original, modified) { const statements = original.getStatements(); const expected = this.getExpectedIndents(original); const lines = modified.split("\n"); for (const statement of statements) { if (statement.getFirstToken().getStart() instanceof virtual_position_1.VirtualPosition) { continue; // macro contents } const exp = expected.shift(); if (exp === undefined || exp < 0) { continue; } const row = statement.getFirstToken().getStart().getRow() - 1; lines[row] = lines[row].trim(); for (let i = 1; i < exp; i++) { lines[row] = " " + lines[row]; } } return lines.join("\n"); } // returns list of expected indentation for each line/statement? getExpectedIndents(file) { var _a; const ret = []; const init = 1; const stack = new Stack(); let indent = init; let parentIsEvent = false; const isDynpro = ((_a = file.getStructure()) === null || _a === void 0 ? void 0 : _a.get()) instanceof structures_1.DynproLogic; let previousStatement = undefined; for (const statement of file.getStatements()) { if (statement.getFirstToken().getStart() instanceof virtual_position_1.VirtualPosition) { continue; // skip macro contents } const type = statement.get(); if (type instanceof Statements.EndIf || type instanceof Statements.EndWhile || type instanceof Statements.EndModule || type instanceof Statements.EndSelect || type instanceof Statements.EndMethod || type instanceof Statements.EndChain || type instanceof Statements.EndAt || type instanceof Statements.Else || type instanceof Statements.EndExec || type instanceof Statements.EndOfDefinition || type instanceof Statements.EndLoop || type instanceof Statements.EndTestInjection || type instanceof Statements.EndTestSeam || type instanceof Statements.EndForm || type instanceof Statements.EndCatch || (this.options.selectionScreenBlockIndentation === true && type instanceof Statements.SelectionScreen && (statement.concatTokens().toUpperCase().includes("END OF SCREEN") || statement.concatTokens().toUpperCase().includes("END OF BLOCK") || statement.concatTokens().toUpperCase().includes("END OF LINE"))) || type instanceof Statements.ElseIf || type instanceof Statements.EndFunction || type instanceof Statements.EndInterface || type instanceof Statements.EndDo) { indent = indent - 2; } else if (type instanceof Statements.StartOfSelection || type instanceof Statements.AtSelectionScreen || type instanceof Statements.AtLineSelection || type instanceof Statements.AtPF || type instanceof Statements.Initialization || type instanceof Statements.AtUserCommand || type instanceof Statements.ProcessAfterInput || type instanceof Statements.ProcessBeforeOutput || type instanceof Statements.ProcessOnValueRequest || type instanceof Statements.TopOfPage || type instanceof Statements.Get || type instanceof Statements.EndOfSelection || type instanceof Statements.LoadOfProgram) { indent = init; parentIsEvent = true; } else if (type instanceof Statements.Form || (type instanceof Statements.Include && parentIsEvent) || (type instanceof Statements.Module && isDynpro === false) || type instanceof Statements.ClassImplementation || type instanceof Statements.ClassDefinition) { indent = init; parentIsEvent = false; } else if (type instanceof Statements.Cleanup || type instanceof Statements.Catch) { indent = stack.peek() - 2; } else if (type instanceof Statements.Public || type instanceof Statements.Protected || type instanceof Statements.Private || type instanceof Statements.WhenType || type instanceof Statements.WhenOthers || type instanceof Statements.When) { indent = stack.peek(); } else if (type instanceof Statements.EndTry) { indent = stack.pop() - (this.options.alignTryCatch ? 2 : 4); } else if (type instanceof Statements.EndClass || type instanceof Statements.EndCase) { indent = stack.pop() - 2; indent = Math.max(indent, init); // maybe move this out of switch before ret.push(indent) } else if (type instanceof _statement_1.Comment || type instanceof Statements.IncludeType || type instanceof _statement_1.Empty || type instanceof _statement_1.MacroContent) { ret.push(-1); previousStatement = statement; continue; } if (previousStatement && !(previousStatement.get() instanceof _statement_1.Comment) && previousStatement.getLastToken().getEnd().getRow() === statement.getFirstToken().getStart().getRow()) { // any indentation allowed if there are multiple statements on the same line ret.push(-1); previousStatement = statement; continue; } ret.push(indent); if (type instanceof Statements.If || type instanceof Statements.While || (type instanceof Statements.Module && isDynpro === false) || type instanceof Statements.SelectLoop || type instanceof Statements.FunctionModule || type instanceof Statements.Interface || type instanceof Statements.Do || type instanceof Statements.At || type instanceof Statements.AtFirst || type instanceof Statements.AtLast || type instanceof Statements.ExecSQL || type instanceof Statements.Catch || type instanceof Statements.ProcessAfterInput || type instanceof Statements.ProcessBeforeOutput || type instanceof Statements.ProcessOnValueRequest || type instanceof Statements.Define || type instanceof Statements.When || type instanceof Statements.WhenType || type instanceof Statements.WhenOthers || type instanceof Statements.Cleanup || type instanceof Statements.Loop || type instanceof Statements.LoopAtScreen || type instanceof Statements.CatchSystemExceptions || type instanceof Statements.Form || type instanceof Statements.Else || type instanceof Statements.ElseIf || type instanceof Statements.MethodImplementation || type instanceof Statements.Chain || type instanceof Statements.TestInjection || type instanceof Statements.TestSeam || (this.options.selectionScreenBlockIndentation === true && type instanceof Statements.SelectionScreen && (statement.concatTokens().toUpperCase().includes("BEGIN OF SCREEN") || statement.concatTokens().toUpperCase().includes("BEGIN OF TABBED BLOCK") || statement.concatTokens().toUpperCase().includes("BEGIN OF BLOCK") || statement.concatTokens().toUpperCase().includes("BEGIN OF LINE"))) || type instanceof Statements.StartOfSelection || type instanceof Statements.Get || type instanceof Statements.AtSelectionScreen || type instanceof Statements.AtLineSelection || type instanceof Statements.LoadOfProgram || type instanceof Statements.Initialization || type instanceof Statements.AtUserCommand || type instanceof Statements.TopOfPage || type instanceof Statements.EndOfSelection || type instanceof Statements.Public || type instanceof Statements.Protected || type instanceof Statements.Private) { indent = indent + 2; } else if (type instanceof Statements.Try) { indent = indent + (this.options.alignTryCatch ? 2 : 4); stack.push(indent); } else if (type instanceof Statements.ClassDefinition || type instanceof Statements.Case || type instanceof Statements.CaseType || type instanceof Statements.ClassImplementation) { indent = indent + (this.skipIndentForGlobalClass(statement) ? 0 : 2); stack.push(indent); } previousStatement = statement; } return ret; } skipIndentForGlobalClass(statement) { if (!this.options.globalClassSkipFirst) { return false; } const type = statement.get(); if (type instanceof Statements.ClassDefinition && statement.findFirstExpression(Expressions.ClassGlobal)) { const className = statement.findFirstExpression(Expressions.ClassName); if (className) { this.globalClasses.add(className.getFirstToken().getStr().toUpperCase()); } return true; } else if (type instanceof Statements.ClassImplementation) { const className = statement.findFirstExpression(Expressions.ClassName); if (className && this.globalClasses.has(className.getFirstToken().getStr().toUpperCase())) { return true; } } return false; } } exports.Indent = Indent; class Stack { constructor() { this.items = []; } push(item) { this.items.push(item); } peek() { return this.items[this.items.length - 1]; } pop() { const peek = this.peek(); this.items = this.items.slice(0, this.items.length - 1); return peek; } } //# sourceMappingURL=indent.js.map