authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-18 18:36:39-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-18 18:36:39-04:00
log21328e0036db94c75083ab8e43ff9195000343f0
treecb6ddae8aaf1d46c7fb33941c9a2ee64cd1e5ba0
parent345f8db1c49efe3d9ca9859a296f24e728a3b43a
signaturelock-open Commit is signed but in an unrecognized format.

zig fmt: handle shebang lines

closes #1546

5 files changed, 46 insertions(+), 6 deletions(-)

std/zig/ast.zig+2
......@@ -469,6 +469,7 @@ pub const Node = struct {
469469 doc_comments: ?*DocComment,
470470 decls: DeclList,
471471 eof_token: TokenIndex,
472 shebang: ?TokenIndex,
472473
473474 pub const DeclList = SegmentedList(*Node, 4);
474475
......@@ -480,6 +481,7 @@ pub const Node = struct {
480481 }
481482
482483 pub fn firstToken(self: *const Root) TokenIndex {
484 if (self.shebang) |shebang| return shebang;
483485 return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken();
484486 }
485487
std/zig/parse.zig+10
......@@ -21,6 +21,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2121 .base = ast.Node{ .id = ast.Node.Id.Root },
2222 .decls = ast.Node.Root.DeclList.init(arena),
2323 .doc_comments = null,
24 .shebang = null,
2425 // initialized when we get the eof token
2526 .eof_token = undefined,
2627 });
......@@ -41,6 +42,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
4142 }
4243 var tok_it = tree.tokens.iterator(0);
4344
45 // skip over shebang line
46 shebang: {
47 const shebang_tok_index = tok_it.index;
48 const shebang_tok_ptr = tok_it.peek() orelse break :shebang;
49 if (shebang_tok_ptr.id != Token.Id.ShebangLine) break :shebang;
50 root_node.shebang = shebang_tok_index;
51 _ = tok_it.next();
52 }
53
4454 // skip over line comments at the top of the file
4555 while (true) {
4656 const next_tok = tok_it.peek() orelse break;
std/zig/parser_test.zig+8
......@@ -1,3 +1,11 @@
1test "zig fmt: shebang line" {
2 try testCanonical(
3 \\#!/usr/bin/env zig
4 \\pub fn main() void {}
5 \\
6 );
7}
8
19test "zig fmt: correctly move doc comments on struct fields" {
210 try testTransform(
311 \\pub const section_64 = extern struct {
std/zig/render.zig+7-1
......@@ -67,8 +67,14 @@ fn renderRoot(
6767 stream: var,
6868 tree: *ast.Tree,
6969) (@typeOf(stream).Child.Error || Error)!void {
70 // render all the line comments at the beginning of the file
7170 var tok_it = tree.tokens.iterator(0);
71
72 // render the shebang line
73 if (tree.root_node.shebang) |shebang| {
74 try stream.write(tree.tokenSlice(shebang));
75 }
76
77 // render all the line comments at the beginning of the file
7278 while (tok_it.next()) |token| {
7379 if (token.id != Token.Id.LineComment) break;
7480 try stream.print("{}\n", mem.trimRight(u8, tree.tokenSlicePtr(token), " "));
std/zig/tokenizer.zig+19-5
......@@ -145,6 +145,7 @@ pub const Token = struct {
145145 LineComment,
146146 DocComment,
147147 BracketStarBracket,
148 ShebangLine,
148149 Keyword_align,
149150 Keyword_and,
150151 Keyword_asm,
......@@ -208,11 +209,24 @@ pub const Tokenizer = struct {
208209 }
209210
210211 pub fn init(buffer: []const u8) Tokenizer {
211 return Tokenizer{
212 .buffer = buffer,
213 .index = 0,
214 .pending_invalid_token = null,
215 };
212 if (mem.startsWith(u8, buffer, "#!")) {
213 const src_start = if (mem.indexOfScalar(u8, buffer, '\n')) |i| i + 1 else buffer.len;
214 return Tokenizer{
215 .buffer = buffer,
216 .index = src_start,
217 .pending_invalid_token = Token{
218 .id = Token.Id.ShebangLine,
219 .start = 0,
220 .end = src_start,
221 },
222 };
223 } else {
224 return Tokenizer{
225 .buffer = buffer,
226 .index = 0,
227 .pending_invalid_token = null,
228 };
229 }
216230 }
217231
218232 const State = enum {