| ... | @@ -3302,6 +3302,26 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi | ... | @@ -3302,6 +3302,26 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi |
| 3302 | | 3302 | |
| 3303 | /// Automatically inserts indentation of written data by keeping | 3303 | /// Automatically inserts indentation of written data by keeping |
| 3304 | /// track of the current indentation level | 3304 | /// track of the current indentation level |
| | 3305 | /// |
| | 3306 | /// We introduce a new indentation scope with pushIndent/popIndent whenever |
| | 3307 | /// we potentially want to introduce an indent after the next newline. |
| | 3308 | /// |
| | 3309 | /// Indentation should only ever increment by one from one line to the next, |
| | 3310 | /// no matter how many new indentation scopes are introduced. This is done by |
| | 3311 | /// only realizing the indentation from the most recent scope. As an example: |
| | 3312 | /// |
| | 3313 | /// while (foo) if (bar) |
| | 3314 | /// f(x); |
| | 3315 | /// |
| | 3316 | /// The body of `while` introduces a new indentation scope and the body of |
| | 3317 | /// `if` also introduces a new indentation scope. When the newline is seen, |
| | 3318 | /// only the indentation scope of the `if` is realized, and the `while` is |
| | 3319 | /// not. |
| | 3320 | /// |
| | 3321 | /// As comments are rendered during space rendering, we need to keep track |
| | 3322 | /// of the appropriate indentation level for them with pushSpace/popSpace. |
| | 3323 | /// This should be done whenever a scope that ends in a .semicolon or a |
| | 3324 | /// .comma is introduced. |
| 3305 | fn AutoIndentingStream(comptime UnderlyingWriter: type) type { | 3325 | fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3306 | return struct { | 3326 | return struct { |
| 3307 | const Self = @This(); | 3327 | const Self = @This(); |
| ... | @@ -3400,8 +3420,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { | ... | @@ -3400,8 +3420,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3400 | | 3420 | |
| 3401 | fn resetLine(self: *Self) void { | 3421 | fn resetLine(self: *Self) void { |
| 3402 | self.current_line_empty = true; | 3422 | self.current_line_empty = true; |
| | 3423 | |
| 3403 | if (self.disable_indent_committing > 0) return; | 3424 | if (self.disable_indent_committing > 0) return; |
| | 3425 | |
| 3404 | if (self.indent_stack.items.len > 0) { | 3426 | if (self.indent_stack.items.len > 0) { |
| | 3427 | // By default, we realize the most recent indentation scope. |
| 3405 | var to_realize = self.indent_stack.items.len - 1; | 3428 | var to_realize = self.indent_stack.items.len - 1; |
| 3406 | | 3429 | |
| 3407 | if (self.indent_stack.items.len >= 2 and | 3430 | if (self.indent_stack.items.len >= 2 and |
| ... | @@ -3409,12 +3432,18 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { | ... | @@ -3409,12 +3432,18 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3409 | self.indent_stack.items[to_realize - 1].realized and | 3432 | self.indent_stack.items[to_realize - 1].realized and |
| 3410 | self.indent_stack.items[to_realize].indent_type == .binop) | 3433 | self.indent_stack.items[to_realize].indent_type == .binop) |
| 3411 | { | 3434 | { |
| 3412 | // collapse one level of indentation in binop after equals sign | 3435 | // If we are in a .binop scope and our direct parent is .after_equals, don't indent. |
| | 3436 | // This ensures correct indentation in the below example: |
| | 3437 | // |
| | 3438 | // const foo = |
| | 3439 | // (x >= 'a' and x <= 'z') or //<-- we are here |
| | 3440 | // (x >= 'A' and x <= 'Z'); |
| | 3441 | // |
| 3413 | return; | 3442 | return; |
| 3414 | } | 3443 | } |
| 3415 | | 3444 | |
| 3416 | if (self.indent_stack.items[to_realize].indent_type == .field_access) { | 3445 | if (self.indent_stack.items[to_realize].indent_type == .field_access) { |
| 3417 | // only realize topmost field_access in a chain | 3446 | // Only realize the top-most field_access in a chain. |
| 3418 | while (to_realize > 0 and self.indent_stack.items[to_realize - 1].indent_type == .field_access) | 3447 | while (to_realize > 0 and self.indent_stack.items[to_realize - 1].indent_type == .field_access) |
| 3419 | to_realize -= 1; | 3448 | to_realize -= 1; |
| 3420 | } | 3449 | } |
| ... | @@ -3425,6 +3454,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { | ... | @@ -3425,6 +3454,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3425 | } | 3454 | } |
| 3426 | } | 3455 | } |
| 3427 | | 3456 | |
| | 3457 | /// Disables indentation level changes during the next newlines until re-enabled. |
| 3428 | pub fn disableIndentCommitting(self: *Self) void { | 3458 | pub fn disableIndentCommitting(self: *Self) void { |
| 3429 | self.disable_indent_committing += 1; | 3459 | self.disable_indent_committing += 1; |
| 3430 | } | 3460 | } |
| ... | @@ -3442,6 +3472,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { | ... | @@ -3442,6 +3472,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3442 | _ = self.space_stack.pop(); | 3472 | _ = self.space_stack.pop(); |
| 3443 | } | 3473 | } |
| 3444 | | 3474 | |
| | 3475 | /// Sets current indentation level to be the same as that of the last pushSpace. |
| 3445 | pub fn enableSpaceMode(self: *Self, space: Space) void { | 3476 | pub fn enableSpaceMode(self: *Self, space: Space) void { |
| 3446 | if (self.space_stack.items.len == 0) return; | 3477 | if (self.space_stack.items.len == 0) return; |
| 3447 | const curr = self.space_stack.getLast(); | 3478 | const curr = self.space_stack.getLast(); |
| ... | @@ -3471,6 +3502,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { | ... | @@ -3471,6 +3502,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3471 | try self.indent_stack.append(.{ .indent_type = indent_type, .realized = false }); | 3502 | try self.indent_stack.append(.{ .indent_type = indent_type, .realized = false }); |
| 3472 | } | 3503 | } |
| 3473 | | 3504 | |
| | 3505 | /// Forces an indentation level to be realized. |
| 3474 | pub fn forcePushIndent(self: *Self, indent_type: IndentType) !void { | 3506 | pub fn forcePushIndent(self: *Self, indent_type: IndentType) !void { |
| 3475 | try self.indent_stack.append(.{ .indent_type = indent_type, .realized = true }); | 3507 | try self.indent_stack.append(.{ .indent_type = indent_type, .realized = true }); |
| 3476 | self.indent_count += 1; | 3508 | self.indent_count += 1; |