From 353f62e15e55f7085a2e2e003ef8686027b2e545 Mon Sep 17 00:00:00 2001
From: Christofer Nolander <christofer@nolander.me>
Date: Wed, 6 Dec 2023 20:50:46 +0100
Subject: [PATCH] allow files with only preprocessor directives

---
 .gitignore       |  1 +
 justfile         |  1 +
 src/analysis.zig |  2 +-
 src/format.zig   | 23 ++++++++++++++++++++++-
 src/main.zig     |  2 +-
 src/syntax.zig   |  2 +-
 6 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8bfefbf..363d5cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ zig-out
 zig-cache
 stderr.log
 __pycache__
+.venv
diff --git a/justfile b/justfile
index 2150aa5..f576bbd 100644
--- a/justfile
+++ b/justfile
@@ -14,6 +14,7 @@ run *ARGS:
     zig build run --summary none {{flags}} -- {{ARGS}}
 
 watch *ARGS:
+    #!/usr/bin/bash
     watchexec -e zig,py,vert,frag,comp -c -- "just ${*@Q} && echo ok"
 
 test:
diff --git a/src/analysis.zig b/src/analysis.zig
index ddc1605..5a3b27e 100644
--- a/src/analysis.zig
+++ b/src/analysis.zig
@@ -690,7 +690,7 @@ fn findIncludedDocuments(
         const directive = parse.parsePreprocessorDirective(line) orelse continue;
         switch (directive) {
             .include => |include| {
-                var include_path = line[include.path.start..include.path.end];
+                const include_path = line[include.path.start..include.path.end];
 
                 const is_relative = !std.fs.path.isAbsolute(include_path);
 
diff --git a/src/format.zig b/src/format.zig
index 6897021..fc37ebe 100644
--- a/src/format.zig
+++ b/src/format.zig
@@ -100,7 +100,7 @@ fn Writer(comptime ChildWriter: type) type {
             self.preceded_by_space = last == ' ' or last == '\n';
         }
 
-        fn emitLeadingTokens(self: *Self, until: u32) !void {
+        fn emitLeadingTokens(self: *Self, until: usize) !void {
             while (self.last_emit < until) {
                 if (self.last_ignored >= self.ignored_tokens.len) break;
 
@@ -180,6 +180,7 @@ fn formatNode(tree: parse.Tree, current: usize, writer: anytype) !void {
             for (children.start..children.end) |child| {
                 try formatNode(tree, child, writer);
             }
+            try writer.emitLeadingTokens(writer.source.len);
             try writer.emitLeadingWhitespace(writer.source.len, .{ .min = 1, .max = 1 });
         },
 
@@ -617,6 +618,26 @@ test "format array declaration" {
     );
 }
 
+test "format only preprocessor" {
+    try expectIsFormatted(
+        \\#version 330
+        \\
+    );
+    try expectIsFormatted(
+        \\#version 330
+        \\#define FOO
+        \\#define BAR
+        \\
+    );
+}
+
+test "format only comments" {
+    try expectIsFormatted(
+        \\// hello world
+        \\
+    );
+}
+
 fn expectIsFormatted(source: []const u8) !void {
     try expectFormat(source, source);
 }
diff --git a/src/main.zig b/src/main.zig
index 62975fb..9c6b670 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -787,7 +787,7 @@ pub const Dispatch = struct {
             return state.success(request.id, null);
         }
 
-        var locations = try state.allocator.alloc(lsp.Location, references.items.len);
+        const locations = try state.allocator.alloc(lsp.Location, references.items.len);
         defer state.allocator.free(locations);
 
         for (references.items, locations) |reference, *location| {
diff --git a/src/syntax.zig b/src/syntax.zig
index feaee39..181ecf0 100644
--- a/src/syntax.zig
+++ b/src/syntax.zig
@@ -260,7 +260,7 @@ pub fn Extractor(comptime expected_tag: Tag, comptime T: type) type {
         pub fn extract(tree: Tree, node: u32, _: void) @This() {
             var matches = MatchFields{};
 
-            var children = tree.children(node);
+            const children = tree.children(node);
             var current = children.start;
 
             inline for (fields) |field| {