authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-23 17:23:53-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-26 11:42:03-08:00
loge03bc7ac78820b7763d6ecd21cfa19653535f8d0
tree0a21038656cb286c26e615dd669976d33ebbdd7a
parent12355cfb4cb14ba78423fb38838f4485bb563c9b

require package names to be valid zig identifiers


1 files changed, 29 insertions(+), 1 deletions(-)

src/Package/Manifest.zig+29-1
......@@ -46,6 +46,8 @@ arena_state: std.heap.ArenaAllocator.State,
4646
4747pub const ParseOptions = struct {
4848 allow_missing_paths_field: bool = false,
49 /// Deprecated, to be removed after 0.14.0 is tagged.
50 allow_name_string: bool = true,
4951};
5052
5153pub const Error = Allocator.Error;
......@@ -72,6 +74,7 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {
7274 .dependencies_node = 0,
7375 .paths = .{},
7476 .allow_missing_paths_field = options.allow_missing_paths_field,
77 .allow_name_string = options.allow_name_string,
7578 .minimum_zig_version = null,
7679 .buf = .{},
7780 };
......@@ -144,6 +147,7 @@ const Parse = struct {
144147 dependencies_node: Ast.Node.Index,
145148 paths: std.StringArrayHashMapUnmanaged(void),
146149 allow_missing_paths_field: bool,
150 allow_name_string: bool,
147151 minimum_zig_version: ?std.SemanticVersion,
148152
149153 const InnerError = error{ ParseFailure, OutOfMemory };
......@@ -175,7 +179,7 @@ const Parse = struct {
175179 have_included_paths = true;
176180 try parseIncludedPaths(p, field_init);
177181 } else if (mem.eql(u8, field_name, "name")) {
178 p.name = try parseString(p, field_init);
182 p.name = try parseName(p, field_init);
179183 have_name = true;
180184 } else if (mem.eql(u8, field_name, "version")) {
181185 p.version_node = field_init;
......@@ -350,6 +354,30 @@ const Parse = struct {
350354 }
351355 }
352356
357 fn parseName(p: *Parse, node: Ast.Node.Index) ![]const u8 {
358 const ast = p.ast;
359 const node_tags = ast.nodes.items(.tag);
360 const main_tokens = ast.nodes.items(.main_token);
361 const main_token = main_tokens[node];
362
363 if (p.allow_name_string and node_tags[node] == .string_literal) {
364 const name = try parseString(p, node);
365 if (!std.zig.isValidId(name))
366 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});
367
368 return name;
369 }
370
371 if (node_tags[node] != .enum_literal)
372 return fail(p, main_token, "expected enum literal", .{});
373
374 const ident_name = ast.tokenSlice(main_token);
375 if (mem.startsWith(u8, ident_name, "@"))
376 return fail(p, main_token, "name must be a valid bare zig identifier", .{});
377
378 return ident_name;
379 }
380
353381 fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 {
354382 const ast = p.ast;
355383 const node_tags = ast.nodes.items(.tag);