mirror of
https://github.com/ziglang/zig.git
synced 2026-10-14 10:27:43 -04:00
std.zig.Ast: improve type safety
This commits adds the following distinct integer types to std.zig.Ast: - OptionalTokenIndex - TokenOffset - OptionalTokenOffset - Node.OptionalIndex - Node.Offset - Node.OptionalOffset The `Node.Index` type has also been converted to a distinct type while `TokenIndex` remains unchanged. `Ast.Node.Data` has also been changed to a (untagged) union to provide safety checks.
This commit is contained in:
25 files changed
+4563
-5060
No files matched your search
+30
-60
@@ -15,8 +15,7 @@ parent: Index,
|
||||
pub const ExtraInfo = struct {
|
||||
is_pub: bool,
|
||||
name: []const u8,
|
||||
/// This might not be a doc_comment token in which case there are no doc comments.
|
||||
first_doc_comment: Ast.TokenIndex,
|
||||
first_doc_comment: Ast.OptionalTokenIndex,
|
||||
};
|
||||
|
||||
pub const Index = enum(u32) {
|
||||
@@ -34,16 +33,14 @@ pub fn is_pub(d: *const Decl) bool {
|
||||
|
||||
pub fn extra_info(d: *const Decl) ExtraInfo {
|
||||
const ast = d.file.get_ast();
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
switch (node_tags[d.ast_node]) {
|
||||
switch (ast.nodeTag(d.ast_node)) {
|
||||
.root => return .{
|
||||
.name = "",
|
||||
.is_pub = true,
|
||||
.first_doc_comment = if (token_tags[0] == .container_doc_comment)
|
||||
0
|
||||
.first_doc_comment = if (ast.tokenTag(0) == .container_doc_comment)
|
||||
.fromToken(0)
|
||||
else
|
||||
token_tags.len - 1,
|
||||
.none,
|
||||
},
|
||||
|
||||
.global_var_decl,
|
||||
@@ -53,7 +50,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
|
||||
=> {
|
||||
const var_decl = ast.fullVarDecl(d.ast_node).?;
|
||||
const name_token = var_decl.ast.mut_token + 1;
|
||||
assert(token_tags[name_token] == .identifier);
|
||||
assert(ast.tokenTag(name_token) == .identifier);
|
||||
const ident_name = ast.tokenSlice(name_token);
|
||||
return .{
|
||||
.name = ident_name,
|
||||
@@ -71,7 +68,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
const fn_proto = ast.fullFnProto(&buf, d.ast_node).?;
|
||||
const name_token = fn_proto.name_token.?;
|
||||
assert(token_tags[name_token] == .identifier);
|
||||
assert(ast.tokenTag(name_token) == .identifier);
|
||||
const ident_name = ast.tokenSlice(name_token);
|
||||
return .{
|
||||
.name = ident_name,
|
||||
@@ -89,9 +86,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
|
||||
|
||||
pub fn value_node(d: *const Decl) ?Ast.Node.Index {
|
||||
const ast = d.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
return switch (node_tags[d.ast_node]) {
|
||||
return switch (ast.nodeTag(d.ast_node)) {
|
||||
.fn_proto,
|
||||
.fn_proto_multi,
|
||||
.fn_proto_one,
|
||||
@@ -106,8 +101,8 @@ pub fn value_node(d: *const Decl) ?Ast.Node.Index {
|
||||
.aligned_var_decl,
|
||||
=> {
|
||||
const var_decl = ast.fullVarDecl(d.ast_node).?;
|
||||
if (token_tags[var_decl.ast.mut_token] == .keyword_const)
|
||||
return var_decl.ast.init_node;
|
||||
if (ast.tokenTag(var_decl.ast.mut_token) == .keyword_const)
|
||||
return var_decl.ast.init_node.unwrap();
|
||||
|
||||
return null;
|
||||
},
|
||||
@@ -148,19 +143,12 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index {
|
||||
pub fn get_type_fn_return_type_fn(decl: *const Decl) ?Decl.Index {
|
||||
if (decl.get_type_fn_return_expr()) |return_expr| {
|
||||
const ast = decl.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
|
||||
switch (node_tags[return_expr]) {
|
||||
.call, .call_comma, .call_one, .call_one_comma => {
|
||||
const node_data = ast.nodes.items(.data);
|
||||
const function = node_data[return_expr].lhs;
|
||||
const token = ast.nodes.items(.main_token)[function];
|
||||
const name = ast.tokenSlice(token);
|
||||
if (decl.lookup(name)) |function_decl| {
|
||||
return function_decl;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
var buffer: [1]Ast.Node.Index = undefined;
|
||||
const call = ast.fullCall(&buffer, return_expr) orelse return null;
|
||||
const token = ast.nodeMainToken(call.ast.fn_expr);
|
||||
const name = ast.tokenSlice(token);
|
||||
if (decl.lookup(name)) |function_decl| {
|
||||
return function_decl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -171,35 +159,18 @@ pub fn get_type_fn_return_expr(decl: *const Decl) ?Ast.Node.Index {
|
||||
switch (decl.categorize()) {
|
||||
.type_function => {
|
||||
const ast = decl.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_data = ast.nodes.items(.data);
|
||||
const body_node = node_data[decl.ast_node].rhs;
|
||||
if (body_node == 0) return null;
|
||||
|
||||
switch (node_tags[body_node]) {
|
||||
.block, .block_semicolon => {
|
||||
const statements = ast.extra_data[node_data[body_node].lhs..node_data[body_node].rhs];
|
||||
// Look for the return statement
|
||||
for (statements) |stmt| {
|
||||
if (node_tags[stmt] == .@"return") {
|
||||
return node_data[stmt].lhs;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
.block_two, .block_two_semicolon => {
|
||||
if (node_tags[node_data[body_node].lhs] == .@"return") {
|
||||
return node_data[node_data[body_node].lhs].lhs;
|
||||
}
|
||||
if (node_data[body_node].rhs != 0 and
|
||||
node_tags[node_data[body_node].rhs] == .@"return")
|
||||
{
|
||||
return node_data[node_data[body_node].rhs].lhs;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
else => return null,
|
||||
const body_node = ast.nodeData(decl.ast_node).node_and_node[1];
|
||||
|
||||
var buf: [2]Ast.Node.Index = undefined;
|
||||
const statements = ast.blockStatements(&buf, body_node) orelse return null;
|
||||
|
||||
for (statements) |stmt| {
|
||||
if (ast.nodeTag(stmt) == .@"return") {
|
||||
return ast.nodeData(stmt).node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
else => return null,
|
||||
}
|
||||
@@ -269,16 +240,15 @@ pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) O
|
||||
}
|
||||
}
|
||||
|
||||
pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.TokenIndex {
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.OptionalTokenIndex {
|
||||
var it = token;
|
||||
while (it > 0) {
|
||||
it -= 1;
|
||||
if (token_tags[it] != .doc_comment) {
|
||||
return it + 1;
|
||||
if (ast.tokenTag(it) != .doc_comment) {
|
||||
return .fromToken(it + 1);
|
||||
}
|
||||
}
|
||||
return it;
|
||||
return .none;
|
||||
}
|
||||
|
||||
/// Successively looks up each component.
|
||||
|
||||
+71
-94
@@ -91,12 +91,10 @@ pub const File = struct {
|
||||
|
||||
pub fn categorize_decl(file_index: File.Index, node: Ast.Node.Index) Category {
|
||||
const ast = file_index.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
switch (node_tags[node]) {
|
||||
switch (ast.nodeTag(node)) {
|
||||
.root => {
|
||||
for (ast.rootDecls()) |member| {
|
||||
switch (node_tags[member]) {
|
||||
switch (ast.nodeTag(member)) {
|
||||
.container_field_init,
|
||||
.container_field_align,
|
||||
.container_field,
|
||||
@@ -113,10 +111,12 @@ pub const File = struct {
|
||||
.aligned_var_decl,
|
||||
=> {
|
||||
const var_decl = ast.fullVarDecl(node).?;
|
||||
if (token_tags[var_decl.ast.mut_token] == .keyword_var)
|
||||
if (ast.tokenTag(var_decl.ast.mut_token) == .keyword_var)
|
||||
return .{ .global_variable = node };
|
||||
const init_node = var_decl.ast.init_node.unwrap() orelse
|
||||
return .{ .global_const = node };
|
||||
|
||||
return categorize_expr(file_index, var_decl.ast.init_node);
|
||||
return categorize_expr(file_index, init_node);
|
||||
},
|
||||
|
||||
.fn_proto,
|
||||
@@ -139,7 +139,7 @@ pub const File = struct {
|
||||
node: Ast.Node.Index,
|
||||
full: Ast.full.FnProto,
|
||||
) Category {
|
||||
return switch (categorize_expr(file_index, full.ast.return_type)) {
|
||||
return switch (categorize_expr(file_index, full.ast.return_type.unwrap().?)) {
|
||||
.namespace, .container, .error_set, .type_type => .{ .type_function = node },
|
||||
else => .{ .function = node },
|
||||
};
|
||||
@@ -155,12 +155,8 @@ pub const File = struct {
|
||||
pub fn categorize_expr(file_index: File.Index, node: Ast.Node.Index) Category {
|
||||
const file = file_index.get();
|
||||
const ast = file_index.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
//log.debug("categorize_expr tag {s}", .{@tagName(node_tags[node])});
|
||||
return switch (node_tags[node]) {
|
||||
//log.debug("categorize_expr tag {s}", .{@tagName(ast.nodeTag(node))});
|
||||
return switch (ast.nodeTag(node)) {
|
||||
.container_decl,
|
||||
.container_decl_trailing,
|
||||
.container_decl_arg,
|
||||
@@ -176,11 +172,11 @@ pub const File = struct {
|
||||
=> {
|
||||
var buf: [2]Ast.Node.Index = undefined;
|
||||
const container_decl = ast.fullContainerDecl(&buf, node).?;
|
||||
if (token_tags[container_decl.ast.main_token] != .keyword_struct) {
|
||||
if (ast.tokenTag(container_decl.ast.main_token) != .keyword_struct) {
|
||||
return .{ .container = node };
|
||||
}
|
||||
for (container_decl.ast.members) |member| {
|
||||
switch (node_tags[member]) {
|
||||
switch (ast.nodeTag(member)) {
|
||||
.container_field_init,
|
||||
.container_field_align,
|
||||
.container_field,
|
||||
@@ -196,7 +192,7 @@ pub const File = struct {
|
||||
=> .{ .error_set = node },
|
||||
|
||||
.identifier => {
|
||||
const name_token = ast.nodes.items(.main_token)[node];
|
||||
const name_token = ast.nodeMainToken(node);
|
||||
const ident_name = ast.tokenSlice(name_token);
|
||||
if (std.mem.eql(u8, ident_name, "type"))
|
||||
return .type_type;
|
||||
@@ -217,9 +213,7 @@ pub const File = struct {
|
||||
},
|
||||
|
||||
.field_access => {
|
||||
const object_node = node_datas[node].lhs;
|
||||
const dot_token = main_tokens[node];
|
||||
const field_ident = dot_token + 1;
|
||||
const object_node, const field_ident = ast.nodeData(node).node_and_token;
|
||||
const field_name = ast.tokenSlice(field_ident);
|
||||
|
||||
switch (categorize_expr(file_index, object_node)) {
|
||||
@@ -259,9 +253,9 @@ pub const File = struct {
|
||||
.@"if",
|
||||
=> {
|
||||
const if_full = ast.fullIf(node).?;
|
||||
if (if_full.ast.else_expr != 0) {
|
||||
if (if_full.ast.else_expr.unwrap()) |else_expr| {
|
||||
const then_cat = categorize_expr_deep(file_index, if_full.ast.then_expr);
|
||||
const else_cat = categorize_expr_deep(file_index, if_full.ast.else_expr);
|
||||
const else_cat = categorize_expr_deep(file_index, else_expr);
|
||||
if (then_cat == .type_type and else_cat == .type_type) {
|
||||
return .type_type;
|
||||
} else if (then_cat == .error_set and else_cat == .error_set) {
|
||||
@@ -320,11 +314,10 @@ pub const File = struct {
|
||||
params: []const Ast.Node.Index,
|
||||
) Category {
|
||||
const ast = file_index.get_ast();
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
const builtin_token = main_tokens[node];
|
||||
const builtin_token = ast.nodeMainToken(node);
|
||||
const builtin_name = ast.tokenSlice(builtin_token);
|
||||
if (std.mem.eql(u8, builtin_name, "@import")) {
|
||||
const str_lit_token = main_tokens[params[0]];
|
||||
const str_lit_token = ast.nodeMainToken(params[0]);
|
||||
const str_bytes = ast.tokenSlice(str_lit_token);
|
||||
const file_path = std.zig.string_literal.parseAlloc(gpa, str_bytes) catch @panic("OOM");
|
||||
defer gpa.free(file_path);
|
||||
@@ -357,14 +350,12 @@ pub const File = struct {
|
||||
|
||||
fn categorize_switch(file_index: File.Index, node: Ast.Node.Index) Category {
|
||||
const ast = file_index.get_ast();
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
|
||||
const case_nodes = ast.extra_data[extra.start..extra.end];
|
||||
const full = ast.fullSwitch(node).?;
|
||||
var all_type_type = true;
|
||||
var all_error_set = true;
|
||||
var any_type = false;
|
||||
if (case_nodes.len == 0) return .{ .global_const = node };
|
||||
for (case_nodes) |case_node| {
|
||||
if (full.ast.cases.len == 0) return .{ .global_const = node };
|
||||
for (full.ast.cases) |case_node| {
|
||||
const case = ast.fullSwitchCase(case_node).?;
|
||||
switch (categorize_expr_deep(file_index, case.ast.target_expr)) {
|
||||
.type_type => {
|
||||
@@ -410,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index {
|
||||
const scope = try gpa.create(Scope);
|
||||
scope.* = .{ .tag = .top };
|
||||
|
||||
const decl_index = try file_index.add_decl(0, .none);
|
||||
try struct_decl(&w, scope, decl_index, 0, ast.containerDeclRoot());
|
||||
const decl_index = try file_index.add_decl(.root, .none);
|
||||
try struct_decl(&w, scope, decl_index, .root, ast.containerDeclRoot());
|
||||
|
||||
const file = file_index.get();
|
||||
shrinkToFit(&file.ident_decls);
|
||||
@@ -505,13 +496,12 @@ pub const Scope = struct {
|
||||
}
|
||||
|
||||
pub fn lookup(start_scope: *Scope, ast: *const Ast, name: []const u8) ?Ast.Node.Index {
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
var it: *Scope = start_scope;
|
||||
while (true) switch (it.tag) {
|
||||
.top => break,
|
||||
.local => {
|
||||
const local: *Local = @alignCast(@fieldParentPtr("base", it));
|
||||
const name_token = main_tokens[local.var_node] + 1;
|
||||
const name_token = ast.nodeMainToken(local.var_node) + 1;
|
||||
const ident_name = ast.tokenSlice(name_token);
|
||||
if (std.mem.eql(u8, ident_name, name)) {
|
||||
return local.var_node;
|
||||
@@ -538,8 +528,6 @@ fn struct_decl(
|
||||
container_decl: Ast.full.ContainerDecl,
|
||||
) Oom!void {
|
||||
const ast = w.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
|
||||
const namespace = try gpa.create(Scope.Namespace);
|
||||
namespace.* = .{
|
||||
@@ -549,7 +537,7 @@ fn struct_decl(
|
||||
try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base);
|
||||
try w.scanDecls(namespace, container_decl.ast.members);
|
||||
|
||||
for (container_decl.ast.members) |member| switch (node_tags[member]) {
|
||||
for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) {
|
||||
.container_field_init,
|
||||
.container_field_align,
|
||||
.container_field,
|
||||
@@ -569,7 +557,7 @@ fn struct_decl(
|
||||
try w.file.get().doctests.put(gpa, member, doctest_node);
|
||||
}
|
||||
const decl_index = try w.file.add_decl(member, parent_decl);
|
||||
const body = if (node_tags[member] == .fn_decl) node_datas[member].rhs else 0;
|
||||
const body = if (ast.nodeTag(member) == .fn_decl) ast.nodeData(member).node_and_node[1].toOptional() else .none;
|
||||
try w.fn_decl(&namespace.base, decl_index, body, full);
|
||||
},
|
||||
|
||||
@@ -584,9 +572,9 @@ fn struct_decl(
|
||||
|
||||
.@"comptime",
|
||||
.@"usingnamespace",
|
||||
=> try w.expr(&namespace.base, parent_decl, node_datas[member].lhs),
|
||||
=> try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node),
|
||||
|
||||
.test_decl => try w.expr(&namespace.base, parent_decl, node_datas[member].rhs),
|
||||
.test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]),
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
@@ -633,13 +621,13 @@ fn fn_decl(
|
||||
w: *Walk,
|
||||
scope: *Scope,
|
||||
parent_decl: Decl.Index,
|
||||
body: Ast.Node.Index,
|
||||
body: Ast.Node.OptionalIndex,
|
||||
full: Ast.full.FnProto,
|
||||
) Oom!void {
|
||||
for (full.ast.params) |param| {
|
||||
try expr(w, scope, parent_decl, param);
|
||||
}
|
||||
try expr(w, scope, parent_decl, full.ast.return_type);
|
||||
try expr(w, scope, parent_decl, full.ast.return_type.unwrap().?);
|
||||
try maybe_expr(w, scope, parent_decl, full.ast.align_expr);
|
||||
try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr);
|
||||
try maybe_expr(w, scope, parent_decl, full.ast.section_expr);
|
||||
@@ -647,17 +635,13 @@ fn fn_decl(
|
||||
try maybe_expr(w, scope, parent_decl, body);
|
||||
}
|
||||
|
||||
fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
|
||||
if (node != 0) return expr(w, scope, parent_decl, node);
|
||||
fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.OptionalIndex) Oom!void {
|
||||
if (node.unwrap()) |n| return expr(w, scope, parent_decl, n);
|
||||
}
|
||||
|
||||
fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
|
||||
assert(node != 0);
|
||||
const ast = w.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
switch (node_tags[node]) {
|
||||
switch (ast.nodeTag(node)) {
|
||||
.root => unreachable, // Top-level declaration.
|
||||
.@"usingnamespace" => unreachable, // Top-level declaration.
|
||||
.test_decl => unreachable, // Top-level declaration.
|
||||
@@ -738,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
.array_access,
|
||||
.switch_range,
|
||||
=> {
|
||||
try expr(w, scope, parent_decl, node_datas[node].lhs);
|
||||
try expr(w, scope, parent_decl, node_datas[node].rhs);
|
||||
const lhs, const rhs = ast.nodeData(node).node_and_node;
|
||||
try expr(w, scope, parent_decl, lhs);
|
||||
try expr(w, scope, parent_decl, rhs);
|
||||
},
|
||||
|
||||
.assign_destructure => {
|
||||
@@ -752,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
.bit_not,
|
||||
.negation,
|
||||
.negation_wrap,
|
||||
.@"return",
|
||||
.deref,
|
||||
.address_of,
|
||||
.optional_type,
|
||||
.unwrap_optional,
|
||||
.grouped_expression,
|
||||
.@"comptime",
|
||||
.@"nosuspend",
|
||||
.@"suspend",
|
||||
.@"await",
|
||||
.@"resume",
|
||||
.@"try",
|
||||
=> try maybe_expr(w, scope, parent_decl, node_datas[node].lhs),
|
||||
=> try expr(w, scope, parent_decl, ast.nodeData(node).node),
|
||||
.unwrap_optional,
|
||||
.grouped_expression,
|
||||
=> try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
|
||||
.@"return" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_node),
|
||||
|
||||
.anyframe_type,
|
||||
.@"break",
|
||||
=> try maybe_expr(w, scope, parent_decl, node_datas[node].rhs),
|
||||
.anyframe_type => try expr(w, scope, parent_decl, ast.nodeData(node).token_and_node[1]),
|
||||
.@"break" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_opt_node[1]),
|
||||
|
||||
.identifier => {
|
||||
const ident_token = main_tokens[node];
|
||||
const ident_token = ast.nodeMainToken(node);
|
||||
const ident_name = ast.tokenSlice(ident_token);
|
||||
if (scope.lookup(ast, ident_name)) |var_node| {
|
||||
try w.file.get().ident_decls.put(gpa, ident_token, var_node);
|
||||
}
|
||||
},
|
||||
.field_access => {
|
||||
const object_node = node_datas[node].lhs;
|
||||
const dot_token = main_tokens[node];
|
||||
const field_ident = dot_token + 1;
|
||||
const object_node, const field_ident = ast.nodeData(node).node_and_token;
|
||||
try w.file.get().token_parents.put(gpa, field_ident, node);
|
||||
// This will populate the left-most field object if it is an
|
||||
// identifier, allowing rendering code to piece together the link.
|
||||
@@ -857,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
.for_simple, .@"for" => {
|
||||
const full = ast.fullFor(node).?;
|
||||
for (full.ast.inputs) |input| {
|
||||
if (node_tags[input] == .for_range) {
|
||||
try expr(w, scope, parent_decl, node_datas[input].lhs);
|
||||
try maybe_expr(w, scope, parent_decl, node_datas[input].rhs);
|
||||
if (ast.nodeTag(input) == .for_range) {
|
||||
const start, const end = ast.nodeData(input).node_and_opt_node;
|
||||
try expr(w, scope, parent_decl, start);
|
||||
try maybe_expr(w, scope, parent_decl, end);
|
||||
} else {
|
||||
try expr(w, scope, parent_decl, input);
|
||||
}
|
||||
@@ -914,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
},
|
||||
|
||||
.array_type_sentinel => {
|
||||
const extra = ast.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
|
||||
try expr(w, scope, parent_decl, node_datas[node].lhs);
|
||||
const len_expr, const extra_index = ast.nodeData(node).node_and_extra;
|
||||
const extra = ast.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
|
||||
try expr(w, scope, parent_decl, len_expr);
|
||||
try expr(w, scope, parent_decl, extra.elem_type);
|
||||
try expr(w, scope, parent_decl, extra.sentinel);
|
||||
},
|
||||
.@"switch", .switch_comma => {
|
||||
const operand_node = node_datas[node].lhs;
|
||||
try expr(w, scope, parent_decl, operand_node);
|
||||
const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
|
||||
const case_nodes = ast.extra_data[extra.start..extra.end];
|
||||
for (case_nodes) |case_node| {
|
||||
const full = ast.fullSwitch(node).?;
|
||||
try expr(w, scope, parent_decl, full.ast.condition);
|
||||
for (full.ast.cases) |case_node| {
|
||||
const case = ast.fullSwitchCase(case_node).?;
|
||||
for (case.ast.values) |value_node| {
|
||||
try expr(w, scope, parent_decl, value_node);
|
||||
@@ -973,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
.fn_proto,
|
||||
=> {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
return fn_decl(w, scope, parent_decl, 0, ast.fullFnProto(&buf, node).?);
|
||||
return fn_decl(w, scope, parent_decl, .none, ast.fullFnProto(&buf, node).?);
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -993,8 +976,7 @@ fn builtin_call(
|
||||
params: []const Ast.Node.Index,
|
||||
) Oom!void {
|
||||
const ast = w.file.get_ast();
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
const builtin_token = main_tokens[node];
|
||||
const builtin_token = ast.nodeMainToken(node);
|
||||
const builtin_name = ast.tokenSlice(builtin_token);
|
||||
if (std.mem.eql(u8, builtin_name, "@This")) {
|
||||
try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl());
|
||||
@@ -1012,13 +994,11 @@ fn block(
|
||||
statements: []const Ast.Node.Index,
|
||||
) Oom!void {
|
||||
const ast = w.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
|
||||
var scope = parent_scope;
|
||||
|
||||
for (statements) |node| {
|
||||
switch (node_tags[node]) {
|
||||
switch (ast.nodeTag(node)) {
|
||||
.global_var_decl,
|
||||
.local_var_decl,
|
||||
.simple_var_decl,
|
||||
@@ -1039,11 +1019,10 @@ fn block(
|
||||
log.debug("walk assign_destructure not implemented yet", .{});
|
||||
},
|
||||
|
||||
.grouped_expression => try expr(w, scope, parent_decl, node_datas[node].lhs),
|
||||
.grouped_expression => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
|
||||
|
||||
.@"defer",
|
||||
.@"errdefer",
|
||||
=> try expr(w, scope, parent_decl, node_datas[node].rhs),
|
||||
.@"defer" => try expr(w, scope, parent_decl, ast.nodeData(node).node),
|
||||
.@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_node[1]),
|
||||
|
||||
else => try expr(w, scope, parent_decl, node),
|
||||
}
|
||||
@@ -1059,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W
|
||||
|
||||
fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.Index) Oom!void {
|
||||
const ast = w.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
|
||||
for (members) |member_node| {
|
||||
const name_token = switch (node_tags[member_node]) {
|
||||
const name_token = switch (ast.nodeTag(member_node)) {
|
||||
.global_var_decl,
|
||||
.local_var_decl,
|
||||
.simple_var_decl,
|
||||
.aligned_var_decl,
|
||||
=> main_tokens[member_node] + 1,
|
||||
=> ast.nodeMainToken(member_node) + 1,
|
||||
|
||||
.fn_proto_simple,
|
||||
.fn_proto_multi,
|
||||
@@ -1078,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In
|
||||
.fn_proto,
|
||||
.fn_decl,
|
||||
=> blk: {
|
||||
const ident = main_tokens[member_node] + 1;
|
||||
if (token_tags[ident] != .identifier) continue;
|
||||
const ident = ast.nodeMainToken(member_node) + 1;
|
||||
if (ast.tokenTag(ident) != .identifier) continue;
|
||||
break :blk ident;
|
||||
},
|
||||
|
||||
.test_decl => {
|
||||
const ident_token = node_datas[member_node].lhs;
|
||||
const is_doctest = token_tags[ident_token] == .identifier;
|
||||
if (is_doctest) {
|
||||
const token_bytes = ast.tokenSlice(ident_token);
|
||||
try namespace.doctests.put(gpa, token_bytes, member_node);
|
||||
const opt_ident_token = ast.nodeData(member_node).opt_token_and_node[0];
|
||||
if (opt_ident_token.unwrap()) |ident_token| {
|
||||
const is_doctest = ast.tokenTag(ident_token) == .identifier;
|
||||
if (is_doctest) {
|
||||
const token_bytes = ast.tokenSlice(ident_token);
|
||||
try namespace.doctests.put(gpa, token_bytes, member_node);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
},
|
||||
|
||||
@@ -41,14 +41,10 @@ pub fn fileSourceHtml(
|
||||
var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty;
|
||||
};
|
||||
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
const token_starts = ast.tokens.items(.start);
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
|
||||
const start_token = ast.firstToken(root_node);
|
||||
const end_token = ast.lastToken(root_node) + 1;
|
||||
|
||||
var cursor: usize = token_starts[start_token];
|
||||
var cursor: usize = ast.tokenStart(start_token);
|
||||
|
||||
var indent: usize = 0;
|
||||
if (std.mem.lastIndexOf(u8, ast.source[0..cursor], "\n")) |newline_index| {
|
||||
@@ -64,8 +60,8 @@ pub fn fileSourceHtml(
|
||||
var next_annotate_index: usize = 0;
|
||||
|
||||
for (
|
||||
token_tags[start_token..end_token],
|
||||
token_starts[start_token..end_token],
|
||||
ast.tokens.items(.tag)[start_token..end_token],
|
||||
ast.tokens.items(.start)[start_token..end_token],
|
||||
start_token..,
|
||||
) |tag, start, token_index| {
|
||||
const between = ast.source[cursor..start];
|
||||
@@ -184,7 +180,7 @@ pub fn fileSourceHtml(
|
||||
.identifier => i: {
|
||||
if (options.fn_link != .none) {
|
||||
const fn_link = options.fn_link.get();
|
||||
const fn_token = main_tokens[fn_link.ast_node];
|
||||
const fn_token = ast.nodeMainToken(fn_link.ast_node);
|
||||
if (token_index == fn_token + 1) {
|
||||
try out.appendSlice(gpa, "<a class=\"tok-fn\" href=\"#");
|
||||
_ = missing_feature_url_escape;
|
||||
@@ -196,7 +192,7 @@ pub fn fileSourceHtml(
|
||||
}
|
||||
}
|
||||
|
||||
if (token_index > 0 and token_tags[token_index - 1] == .keyword_fn) {
|
||||
if (token_index > 0 and ast.tokenTag(token_index - 1) == .keyword_fn) {
|
||||
try out.appendSlice(gpa, "<span class=\"tok-fn\">");
|
||||
try appendEscaped(out, slice);
|
||||
try out.appendSlice(gpa, "</span>");
|
||||
@@ -358,16 +354,11 @@ fn walkFieldAccesses(
|
||||
node: Ast.Node.Index,
|
||||
) Oom!void {
|
||||
const ast = file_index.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
assert(node_tags[node] == .field_access);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
const object_node = node_datas[node].lhs;
|
||||
const dot_token = main_tokens[node];
|
||||
const field_ident = dot_token + 1;
|
||||
switch (node_tags[object_node]) {
|
||||
assert(ast.nodeTag(node) == .field_access);
|
||||
const object_node, const field_ident = ast.nodeData(node).node_and_token;
|
||||
switch (ast.nodeTag(object_node)) {
|
||||
.identifier => {
|
||||
const lhs_ident = main_tokens[object_node];
|
||||
const lhs_ident = ast.nodeMainToken(object_node);
|
||||
try resolveIdentLink(file_index, out, lhs_ident);
|
||||
},
|
||||
.field_access => {
|
||||
|
||||
+34
-48
@@ -124,7 +124,9 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
|
||||
@memcpy(g.full_path_search_text_lower.items, g.full_path_search_text.items);
|
||||
|
||||
const ast = decl.file.get_ast();
|
||||
try collect_docs(&g.doc_search_text, ast, info.first_doc_comment);
|
||||
if (info.first_doc_comment.unwrap()) |first_doc_comment| {
|
||||
try collect_docs(&g.doc_search_text, ast, first_doc_comment);
|
||||
}
|
||||
|
||||
if (ignore_case) {
|
||||
ascii_lower(g.full_path_search_text_lower.items);
|
||||
@@ -227,18 +229,15 @@ const ErrorIdentifier = packed struct(u64) {
|
||||
fn hasDocs(ei: ErrorIdentifier) bool {
|
||||
const decl_index = ei.decl_index;
|
||||
const ast = decl_index.get().file.get_ast();
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
const token_index = ei.token_index;
|
||||
if (token_index == 0) return false;
|
||||
return token_tags[token_index - 1] == .doc_comment;
|
||||
return ast.tokenTag(token_index - 1) == .doc_comment;
|
||||
}
|
||||
|
||||
fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void {
|
||||
const decl_index = ei.decl_index;
|
||||
const ast = decl_index.get().file.get_ast();
|
||||
const name = ast.tokenSlice(ei.token_index);
|
||||
const first_doc_comment = Decl.findFirstDocComment(ast, ei.token_index);
|
||||
const has_docs = ast.tokens.items(.tag)[first_doc_comment] == .doc_comment;
|
||||
const has_link = base_decl != decl_index;
|
||||
|
||||
try out.appendSlice(gpa, "<dt>");
|
||||
@@ -253,7 +252,7 @@ const ErrorIdentifier = packed struct(u64) {
|
||||
}
|
||||
try out.appendSlice(gpa, "</dt>");
|
||||
|
||||
if (has_docs) {
|
||||
if (Decl.findFirstDocComment(ast, ei.token_index).unwrap()) |first_doc_comment| {
|
||||
try out.appendSlice(gpa, "<dd>");
|
||||
try render_docs(out, decl_index, first_doc_comment, false);
|
||||
try out.appendSlice(gpa, "</dd>");
|
||||
@@ -319,17 +318,16 @@ fn addErrorsFromExpr(
|
||||
) Oom!void {
|
||||
const decl = decl_index.get();
|
||||
const ast = decl.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
|
||||
switch (decl.file.categorize_expr(node)) {
|
||||
.error_set => |n| switch (node_tags[n]) {
|
||||
.error_set => |n| switch (ast.nodeTag(n)) {
|
||||
.error_set_decl => {
|
||||
try addErrorsFromNode(decl_index, out, node);
|
||||
},
|
||||
.merge_error_sets => {
|
||||
try addErrorsFromExpr(decl_index, out, node_datas[node].lhs);
|
||||
try addErrorsFromExpr(decl_index, out, node_datas[node].rhs);
|
||||
const lhs, const rhs = ast.nodeData(n).node_and_node;
|
||||
try addErrorsFromExpr(decl_index, out, lhs);
|
||||
try addErrorsFromExpr(decl_index, out, rhs);
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
@@ -347,11 +345,9 @@ fn addErrorsFromNode(
|
||||
) Oom!void {
|
||||
const decl = decl_index.get();
|
||||
const ast = decl.file.get_ast();
|
||||
const main_tokens = ast.nodes.items(.main_token);
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
const error_token = main_tokens[node];
|
||||
const error_token = ast.nodeMainToken(node);
|
||||
var tok_i = error_token + 2;
|
||||
while (true) : (tok_i += 1) switch (token_tags[tok_i]) {
|
||||
while (true) : (tok_i += 1) switch (ast.tokenTag(tok_i)) {
|
||||
.doc_comment, .comma => {},
|
||||
.identifier => {
|
||||
const name = ast.tokenSlice(tok_i);
|
||||
@@ -391,15 +387,13 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index {
|
||||
|
||||
switch (decl.categorize()) {
|
||||
.type_function => {
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
|
||||
// If the type function returns a reference to another type function, get the fields from there
|
||||
if (decl.get_type_fn_return_type_fn()) |function_decl| {
|
||||
return decl_fields_fallible(function_decl);
|
||||
}
|
||||
// If the type function returns a container, such as a `struct`, read that container's fields
|
||||
if (decl.get_type_fn_return_expr()) |return_expr| {
|
||||
switch (node_tags[return_expr]) {
|
||||
switch (ast.nodeTag(return_expr)) {
|
||||
.container_decl, .container_decl_trailing, .container_decl_two, .container_decl_two_trailing, .container_decl_arg, .container_decl_arg_trailing => {
|
||||
return ast_decl_fields_fallible(ast, return_expr);
|
||||
},
|
||||
@@ -420,10 +414,9 @@ fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.In
|
||||
var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty;
|
||||
};
|
||||
g.result.clearRetainingCapacity();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
var buf: [2]Ast.Node.Index = undefined;
|
||||
const container_decl = ast.fullContainerDecl(&buf, ast_index) orelse return &.{};
|
||||
for (container_decl.ast.members) |member_node| switch (node_tags[member_node]) {
|
||||
for (container_decl.ast.members) |member_node| switch (ast.nodeTag(member_node)) {
|
||||
.container_field_init,
|
||||
.container_field_align,
|
||||
.container_field,
|
||||
@@ -478,9 +471,8 @@ fn decl_field_html_fallible(
|
||||
try out.appendSlice(gpa, "</code></pre>");
|
||||
|
||||
const field = ast.fullContainerField(field_node).?;
|
||||
const first_doc_comment = Decl.findFirstDocComment(ast, field.firstToken());
|
||||
|
||||
if (ast.tokens.items(.tag)[first_doc_comment] == .doc_comment) {
|
||||
if (Decl.findFirstDocComment(ast, field.firstToken()).unwrap()) |first_doc_comment| {
|
||||
try out.appendSlice(gpa, "<div class=\"fieldDocs\">");
|
||||
try render_docs(out, decl_index, first_doc_comment, false);
|
||||
try out.appendSlice(gpa, "</div>");
|
||||
@@ -494,14 +486,13 @@ fn decl_param_html_fallible(
|
||||
) !void {
|
||||
const decl = decl_index.get();
|
||||
const ast = decl.file.get_ast();
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
const colon = ast.firstToken(param_node) - 1;
|
||||
const name_token = colon - 1;
|
||||
const first_doc_comment = f: {
|
||||
var it = ast.firstToken(param_node);
|
||||
while (it > 0) {
|
||||
it -= 1;
|
||||
switch (token_tags[it]) {
|
||||
switch (ast.tokenTag(it)) {
|
||||
.doc_comment, .colon, .identifier, .keyword_comptime, .keyword_noalias => {},
|
||||
else => break,
|
||||
}
|
||||
@@ -516,7 +507,7 @@ fn decl_param_html_fallible(
|
||||
try fileSourceHtml(decl.file, out, param_node, .{});
|
||||
try out.appendSlice(gpa, "</code></pre>");
|
||||
|
||||
if (ast.tokens.items(.tag)[first_doc_comment] == .doc_comment) {
|
||||
if (ast.tokenTag(first_doc_comment) == .doc_comment) {
|
||||
try out.appendSlice(gpa, "<div class=\"fieldDocs\">");
|
||||
try render_docs(out, decl_index, first_doc_comment, false);
|
||||
try out.appendSlice(gpa, "</div>");
|
||||
@@ -526,10 +517,8 @@ fn decl_param_html_fallible(
|
||||
export fn decl_fn_proto_html(decl_index: Decl.Index, linkify_fn_name: bool) String {
|
||||
const decl = decl_index.get();
|
||||
const ast = decl.file.get_ast();
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
const proto_node = switch (node_tags[decl.ast_node]) {
|
||||
.fn_decl => node_datas[decl.ast_node].lhs,
|
||||
const proto_node = switch (ast.nodeTag(decl.ast_node)) {
|
||||
.fn_decl => ast.nodeData(decl.ast_node).node_and_node[0],
|
||||
|
||||
.fn_proto,
|
||||
.fn_proto_one,
|
||||
@@ -586,17 +575,16 @@ export fn decl_parent(decl_index: Decl.Index) Decl.Index {
|
||||
return decl.parent;
|
||||
}
|
||||
|
||||
export fn fn_error_set(decl_index: Decl.Index) Ast.Node.Index {
|
||||
export fn fn_error_set(decl_index: Decl.Index) Ast.Node.OptionalIndex {
|
||||
const decl = decl_index.get();
|
||||
const ast = decl.file.get_ast();
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
const full = ast.fullFnProto(&buf, decl.ast_node).?;
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
const node_datas = ast.nodes.items(.data);
|
||||
return switch (node_tags[full.ast.return_type]) {
|
||||
.error_set_decl => full.ast.return_type,
|
||||
.error_union => node_datas[full.ast.return_type].lhs,
|
||||
else => 0,
|
||||
const return_type = full.ast.return_type.unwrap().?;
|
||||
return switch (ast.nodeTag(return_type)) {
|
||||
.error_set_decl => return_type.toOptional(),
|
||||
.error_union => ast.nodeData(return_type).node_and_node[0].toOptional(),
|
||||
else => .none,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -609,21 +597,19 @@ export fn decl_file_path(decl_index: Decl.Index) String {
|
||||
export fn decl_category_name(decl_index: Decl.Index) String {
|
||||
const decl = decl_index.get();
|
||||
const ast = decl.file.get_ast();
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
const name = switch (decl.categorize()) {
|
||||
.namespace, .container => |node| {
|
||||
const node_tags = ast.nodes.items(.tag);
|
||||
if (node_tags[decl.ast_node] == .root)
|
||||
if (ast.nodeTag(decl.ast_node) == .root)
|
||||
return String.init("struct");
|
||||
string_result.clearRetainingCapacity();
|
||||
var buf: [2]Ast.Node.Index = undefined;
|
||||
const container_decl = ast.fullContainerDecl(&buf, node).?;
|
||||
if (container_decl.layout_token) |t| {
|
||||
if (token_tags[t] == .keyword_extern) {
|
||||
if (ast.tokenTag(t) == .keyword_extern) {
|
||||
string_result.appendSlice(gpa, "extern ") catch @panic("OOM");
|
||||
}
|
||||
}
|
||||
const main_token_tag = token_tags[container_decl.ast.main_token];
|
||||
const main_token_tag = ast.tokenTag(container_decl.ast.main_token);
|
||||
string_result.appendSlice(gpa, main_token_tag.lexeme().?) catch @panic("OOM");
|
||||
return String.init(string_result.items);
|
||||
},
|
||||
@@ -656,7 +642,9 @@ export fn decl_name(decl_index: Decl.Index) String {
|
||||
export fn decl_docs_html(decl_index: Decl.Index, short: bool) String {
|
||||
const decl = decl_index.get();
|
||||
string_result.clearRetainingCapacity();
|
||||
render_docs(&string_result, decl_index, decl.extra_info().first_doc_comment, short) catch @panic("OOM");
|
||||
if (decl.extra_info().first_doc_comment.unwrap()) |first_doc_comment| {
|
||||
render_docs(&string_result, decl_index, first_doc_comment, short) catch @panic("OOM");
|
||||
}
|
||||
return String.init(string_result.items);
|
||||
}
|
||||
|
||||
@@ -665,10 +653,9 @@ fn collect_docs(
|
||||
ast: *const Ast,
|
||||
first_doc_comment: Ast.TokenIndex,
|
||||
) Oom!void {
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
list.clearRetainingCapacity();
|
||||
var it = first_doc_comment;
|
||||
while (true) : (it += 1) switch (token_tags[it]) {
|
||||
while (true) : (it += 1) switch (ast.tokenTag(it)) {
|
||||
.doc_comment, .container_doc_comment => {
|
||||
// It is tempting to trim this string but think carefully about how
|
||||
// that will affect the markdown parser.
|
||||
@@ -687,12 +674,11 @@ fn render_docs(
|
||||
) Oom!void {
|
||||
const decl = decl_index.get();
|
||||
const ast = decl.file.get_ast();
|
||||
const token_tags = ast.tokens.items(.tag);
|
||||
|
||||
var parser = try markdown.Parser.init(gpa);
|
||||
defer parser.deinit();
|
||||
var it = first_doc_comment;
|
||||
while (true) : (it += 1) switch (token_tags[it]) {
|
||||
while (true) : (it += 1) switch (ast.tokenTag(it)) {
|
||||
.doc_comment, .container_doc_comment => {
|
||||
const line = ast.tokenSlice(it)[3..];
|
||||
if (short and line.len == 0) break;
|
||||
@@ -767,9 +753,9 @@ export fn decl_type_html(decl_index: Decl.Index) String {
|
||||
t: {
|
||||
// If there is an explicit type, use it.
|
||||
if (ast.fullVarDecl(decl.ast_node)) |var_decl| {
|
||||
if (var_decl.ast.type_node != 0) {
|
||||
if (var_decl.ast.type_node.unwrap()) |type_node| {
|
||||
string_result.appendSlice(gpa, "<code>") catch @panic("OOM");
|
||||
fileSourceHtml(decl.file, &string_result, var_decl.ast.type_node, .{
|
||||
fileSourceHtml(decl.file, &string_result, type_node, .{
|
||||
.skip_comments = true,
|
||||
.collapse_whitespace = true,
|
||||
}) catch |e| {
|
||||
|
||||
Reference in new issue
Block a user