UNPKG

5.02 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4var coffee_lex_1 = require("coffee-lex");
5var notNull_1 = require("../utils/notNull");
6var NodePatcher_1 = require("./NodePatcher");
7var SharedBlockPatcher = /** @class */ (function (_super) {
8 tslib_1.__extends(SharedBlockPatcher, _super);
9 function SharedBlockPatcher(patcherContext, statements) {
10 var _this = _super.call(this, patcherContext) || this;
11 _this.shouldPatchInline = null;
12 _this.statements = statements;
13 return _this;
14 }
15 /**
16 * Insert statements somewhere in this block.
17 */
18 SharedBlockPatcher.prototype.insertStatementsAtIndex = function (statements, index) {
19 var _this = this;
20 var separator = this.inline() ? '; ' : ';\n';
21 if (index === this.statements.length) {
22 var lastStatement = this.statements[this.statements.length - 1];
23 var terminatorTokenIndex = this.context.sourceTokens.indexOfTokenMatchingPredicate(function (token) { return token.type === coffee_lex_1.SourceType.NEWLINE || token.type === coffee_lex_1.SourceType.SEMICOLON; }, lastStatement.outerEndTokenIndex);
24 var insertionPoint_1 = terminatorTokenIndex
25 ? notNull_1.default(this.sourceTokenAtIndex(terminatorTokenIndex)).start
26 : lastStatement.outerEnd;
27 insertionPoint_1 = Math.min(insertionPoint_1, this.getBoundingPatcher().innerEnd);
28 var indent_1 = lastStatement.getIndent();
29 statements.forEach(function (line) {
30 var sep = line.trim().startsWith('//') ? '\n' : separator;
31 _this.insert(insertionPoint_1, "" + sep + indent_1 + line);
32 });
33 }
34 else {
35 var statementToInsertBefore = this.statements[index];
36 var insertionPoint_2 = statementToInsertBefore.outerStart;
37 var indent_2 = statementToInsertBefore.getIndent();
38 statements.forEach(function (line) {
39 var sep = line.trim().startsWith('//') ? '\n' : separator;
40 _this.insert(insertionPoint_2, "" + line + sep + indent_2);
41 });
42 }
43 };
44 /**
45 * Insert a statement before the current block. Since blocks can be patched in
46 * a number of ways, this needs to handle a few cases:
47 * - If it's completely inline, we don't deal with any indentation and just
48 * put a semicolon-separated statement before the start.
49 * - If it's a normal non-inline block, we insert the statement beforehand
50 * with the given indentation. However, `this.outerStart` is the first
51 * non-whitespace character of the first line, so it's already indented, so
52 * if we want to add a line with *less* indentation, it's a lot more tricky.
53 * We handle this by walking backward to the previous newline and inserting
54 * a new line from there. This allows the prepended line to have whatever
55 * indentation level we want.
56 * - In some cases, such as nontrivial loop expressions with an inline body,
57 * the source CoffeeScript is inline, but we want the result to be
58 * non-inline, so we need to be a lot more careful. The normal non-inline
59 * strategy won't work because there's no newline to walk back to in the
60 * source CoffeeScript, so the strategy is to instead always insert at
61 * `this.outerStart`. That means that the indentation for the actual body
62 * needs to be done later, just before the body itself is patched. See the
63 * uses of shouldConvertInlineBodyToNonInline in LoopPatcher for an example.
64 */
65 SharedBlockPatcher.prototype.insertLineBefore = function (statement, indent) {
66 if (indent === void 0) { indent = this.getIndent(); }
67 if (this.inline()) {
68 this.insert(this.outerStart, statement + "; ");
69 }
70 else if (this.node.inline) {
71 this.insert(this.outerStart, "" + indent + statement + ";\n");
72 }
73 else {
74 var insertIndex = this.outerStart;
75 while (insertIndex > 0 && this.context.source[insertIndex] !== '\n') {
76 insertIndex--;
77 }
78 this.insert(insertIndex, "\n" + indent + statement + ";");
79 }
80 };
81 SharedBlockPatcher.prototype.insertLineAfter = function (statement, indent) {
82 if (this.inline()) {
83 this.insert(this.outerEnd, "; " + statement);
84 }
85 else {
86 this.insert(this.outerEnd, "\n" + indent + statement + ";");
87 }
88 };
89 /**
90 * Gets whether this patcher's block is inline (on the same line as the node
91 * that contains it) or not.
92 */
93 SharedBlockPatcher.prototype.inline = function () {
94 if (this.shouldPatchInline !== null) {
95 return this.shouldPatchInline;
96 }
97 return this.node.inline;
98 };
99 return SharedBlockPatcher;
100}(NodePatcher_1.default));
101exports.default = SharedBlockPatcher;