From ec7f4d1faab8aa9b797f96d233d2ca12c99d2179 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 11 Mar 2022 18:26:21 +0100 Subject: [PATCH] autodoc: add support for anytype and improve semantics for array length --- lib/docs/main.js | 179 +++++++++++++++++++++++++++++------------------ src/Autodoc.zig | 85 +++++++++++++++++++--- 2 files changed, 187 insertions(+), 77 deletions(-) diff --git a/lib/docs/main.js b/lib/docs/main.js index 1f986cb87d..b230777255 100644 --- a/lib/docs/main.js +++ b/lib/docs/main.js @@ -187,7 +187,7 @@ i += 1; console.assert(isDecl(decl)); if ("type" in decl.value) { - return typeTypeId; + return { type: typeTypeId }; } if ("declPath" in decl.value) { @@ -232,6 +232,10 @@ return fn_type.ret; } + if ("void" in decl.value) { + return { type: typeTypeId }; + } + console.log("TODO: handle in `typeOfDecl` more cases: ", decl); console.assert(false); throw {}; @@ -472,22 +476,9 @@ var html = '
' + escapeHtml(fieldNode.name) + ": ";
             if (isVarArgs && i === typeObj.params.length - 1) {
                 html += '...';
-            } else if ("declRef" in value) {
-                var decl = zigAnalysis.decls[value.declRef];
-                var val = resolveValue(decl.value);
-                var valType = zigAnalysis.types[argTypeIndex];
-
-                var valTypeName = typeShorthandName(valType);
-
-                html += '';
-                html += '' + escapeHtml(decl.name) + '';
-                html += '';
-                html += ' ('+ valTypeName +')';
-            } else if ("type" in value) {
-                var name = zigAnalysis.types[value.type].name;
-                html += '' + escapeHtml(name) + '';
             } else {
-                html += 'var';
+                var name = typeValueName(value);
+                html += '' + name + '';
             }
 
             html += ',
'; @@ -657,24 +648,52 @@ } function typeValueName(typeValue, wantHtml, wantLink, fnDecl, linkFnNameDecl) { + + if ("int" in typeValue) { + return typeValue.int.value; + } + if ("call" in typeValue) { + var result = ""; + var call = zigAnalysis.calls[typeValue.call]; + var functionName = typeValueName(call.func); + result += functionName + "("; + for (var j = 0; j < call.args.length; j += 1) { + result += typeValueName(call.args[j]); + if (j != call.args.length -1) result += ","; + } + + return result + ")"; + } + if ("comptimeExpr" in typeValue) { + return "[ComptimeExpr]"; + } if ("declPath" in typeValue) { - if (typeValue.hasCte) { - // TODO: find the cte, print it nicely - if (wantLink) { - return '[ComptimeExpr]'; - } else { - return "[ComptimeExpr]"; - } - } - var declIndex = typeValue.declPath[0]; - var name = zigAnalysis.decls[declIndex].name; - var declPath = getCanonDeclPath(declIndex); - if (wantLink) { - var nl = navLink(declPath.pkgNames, declPath.declNames); - return '' + name + ''; - } else { - return name; + var result = ""; + for (var j = typeValue.declPath.length - 1; j >= 0; j--) { + var decl = zigAnalysis.decls[typeValue.declPath[j]]; + + // TODO: handle nested decl paths properly! + if (typeValue.hasCte) { + if (wantHtml) + result += "[ComptimeExpr]"; + else + result += "[ComptimeExpr]"; + break; + } + var name = escapeHtml(decl.name); + if (wantHtml) { + result += ''; + result += '' + + name + ''; + result += ''; + } else { + result += name; + } + + if (j != 0) result += "."; } + + return result; } console.assert("type" in typeValue) @@ -760,10 +779,11 @@ switch (typeObj.kind) { case typeKinds.Array: var name = "["; + var lenName = typeValueName(typeObj.len, wantHtml); if (wantHtml) { - name += '' + typeObj.len + ''; + name += '' + lenName + ''; } else { - name += typeObj.len; + name += lenName; } name += "]"; name += typeValueName(typeObj.child, wantHtml, wantSubLink, null); @@ -986,12 +1006,16 @@ } else { var decl = zigAnalysis.decls[value.declPath[0]]; var val = resolveValue(decl.value); - var valType = zigAnalysis.types[argTypeIndex]; - - var valTypeName = typeShorthandName(valType); - payloadHtml += ''; - payloadHtml += '' + escapeHtml(decl.name) + ''; - payloadHtml += ''; + if ("comptimeExpr" in val) { + payloadHtml += "[ComptimeExpr]"; + } else { + console.assert("type" in val); + var valType = zigAnalysis.types[val.type]; + var valTypeName = typeShorthandName(valType); + payloadHtml += ''; + payloadHtml += '' + escapeHtml(decl.name) + ''; + payloadHtml += ''; + } } } else if ("type" in value) { var name = typeValueName(value, false); @@ -1258,6 +1282,43 @@ } } } + + declLen = container.privDecls ? container.privDecls.length : 0; + for (var i = 0; i < declLen; i += 1) { + var decl = zigAnalysis.decls[container.privDecls[i]]; + var declValue = resolveValue(decl.value); + + if (decl.kind === 'var') { + varsList.push(decl); + continue; + } + + if (decl.kind === 'const') { + if (!("type" in declValue)){ + valsList.push(decl); + } else { + var value = zigAnalysis.types[declValue.type]; + var kind = value.kind; + if (kind === typeKinds.Fn) { + // TODO: handle CTE return types when we know their type. + const resVal = resolveValue(value.ret); + if ("type" in resVal && resVal.type == typeTypeId) { + typesList.push(decl); + } else { + fnsList.push(decl); + } + + } else if (typeIsErrSet(declValue.type)) { + errSetsList.push(decl); + } else if (typeIsStructWithNoFields(declValue.type)) { + namespacesList.push(decl); + } else { + typesList.push(decl); + } + } + } + } + typesList.sort(byNameProperty); namespacesList.sort(byNameProperty); errSetsList.sort(byNameProperty); @@ -1349,35 +1410,9 @@ html += ": "; if (field.failure === true) { html += '#FAILURE#'; - } else if ("declPath" in field) { - for (var j = field.declPath.length - 1; j >= 0; j--) { - var decl = zigAnalysis.decls[field.declPath[j]]; - - // TODO: handle nested decl paths properly! - if (field.hasCte) { - html += "[ComptimeExpr]"; - break; - } - - html += ''; - html += '' + - escapeHtml(decl.name) + ''; - html += ''; - if (j != 0) html += "."; - } - // at the end of the for loop this is the value of `decl` - //decl = zigAnalysis.decls[field.declPath[0]]; - - var val = resolveValue(decl.value); - console.assert("type" in val); - var valType = zigAnalysis.types[val.type]; - var valTypeName = typeShorthandName(valType); - html += ' ('+ valTypeName +')'; - } else if ("type" in field) { - var name = zigAnalysis.types[field.type].name; - html += '' + escapeHtml(name) + ''; } else { - html += 'var'; + var name = typeValueName(field); + html += ''+ name +''; } } @@ -1544,6 +1579,14 @@ return childDecl; } } + if (!parentType.privDecls) return null; + for (var i = 0; i < parentType.privDecls.length; i += 1) { + var declIndex = parentType.privDecls[i]; + var childDecl = zigAnalysis.decls[declIndex]; + if (childDecl.name === childName) { + return childDecl; + } + } return null; } diff --git a/src/Autodoc.zig b/src/Autodoc.zig index d5efd5e85e..5da200240c 100644 --- a/src/Autodoc.zig +++ b/src/Autodoc.zig @@ -92,7 +92,15 @@ pub fn generateZirData(self: *Autodoc) !void { // instead of just assinging "array" to them. break :blk .{ .Array = .{ - .len = 1, + .len = .{ + .int = .{ + .typeRef = .{ + .type = @enumToInt(Ref.usize_type), + }, + .value = 1, + .negated = false, + }, + }, .child = .{ .type = 0 }, }, }; @@ -374,7 +382,7 @@ const DocData = struct { child: TypeRef, }, Array: struct { - len: usize, + len: WalkResult, child: TypeRef, }, Struct: struct { @@ -516,6 +524,7 @@ const DocData = struct { /// An example of indidirectness is `const bar = foo;`. const TypeRef = union(enum) { unspecified, + @"anytype", declPath: DeclPath, type: usize, // index in `types` comptimeExpr: usize, // index in `comptimeExprs` @@ -530,10 +539,10 @@ const DocData = struct { w: anytype, ) !void { switch (self) { - .unspecified => { + .unspecified, .@"anytype" => { try w.print( - \\{{ "unspecified":{{}} }} - , .{}); + \\{{ "{s}":{{}} }} + , .{@tagName(self)}); }, .type, .comptimeExpr, .call => |v| { @@ -566,6 +575,7 @@ const DocData = struct { @"undefined": TypeRef, @"struct": Struct, bool: bool, + @"anytype", type: usize, // index in `types` declPath: DeclPath, int: struct { @@ -600,7 +610,7 @@ const DocData = struct { w: anytype, ) !void { switch (self) { - .void, .@"unreachable" => { + .void, .@"unreachable", .@"anytype" => { try w.print( \\{{ "{s}":{{}} }} , .{@tagName(self)}); @@ -755,6 +765,13 @@ fn walkInstruction( }, }; }, + .error_union_type => { + const pl_node = data[inst_index].pl_node; + const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index); + + // TODO: return the actual error union instread of cheating + return self.walkRef(file, parent_scope, extra.data.rhs); + }, .ptr_type_simple => { const ptr = data[inst_index].ptr_type_simple; const type_slot_index = self.types.items.len; @@ -768,6 +785,20 @@ fn walkInstruction( return DocData.WalkResult{ .type = type_slot_index }; }, + .array_type => { + const bin = data[inst_index].bin; + const len = try self.walkRef(file, parent_scope, bin.lhs); + const child = walkResultToTypeRef(try self.walkRef(file, parent_scope, bin.rhs)); + + const type_slot_index = self.types.items.len; + try self.types.append(self.arena, .{ + .Array = .{ + .len = len, + .child = child, + }, + }); + return DocData.WalkResult{ .type = type_slot_index }; + }, .array_init => { const pl_node = data[inst_index].pl_node; const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index); @@ -780,7 +811,13 @@ fn walkInstruction( const type_slot_index = self.types.items.len; try self.types.append(self.arena, .{ .Array = .{ - .len = operands.len, + .len = .{ + .int = .{ + .typeRef = .{ .type = @enumToInt(Ref.usize_type) }, + .value = operands.len, + .negated = false, + }, + }, .child = typeOfWalkResult(array_data[0]), }, }); @@ -1017,6 +1054,23 @@ fn walkInstruction( .{@tagName(tags[param_index])}, ); }, + .param_anytype => { + // TODO: where are the doc comments? + const str_tok = data[param_index].str_tok; + + const name = str_tok.get(file.zir); + + param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len); + self.ast_nodes.appendAssumeCapacity(.{ + .name = name, + .docs = "", + .@"comptime" = true, + }); + + param_type_refs.appendAssumeCapacity( + DocData.TypeRef{ .@"anytype" = {} }, + ); + }, .param, .param_comptime => { const pl_tok = data[param_index].pl_tok; const extra = file.zir.extraData(Zir.Inst.Param, pl_tok.payload_index); @@ -1024,10 +1078,11 @@ fn walkInstruction( file.zir.nullTerminatedString(extra.data.doc_comment) else ""; + const name = file.zir.nullTerminatedString(extra.data.name); param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len); self.ast_nodes.appendAssumeCapacity(.{ - .name = file.zir.nullTerminatedString(extra.data.name), + .name = name, .docs = doc_comment, .@"comptime" = tags[param_index] == .param_comptime, }); @@ -1094,6 +1149,18 @@ fn walkInstruction( .{@tagName(extended.opcode)}, ); }, + .variable => { + const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); + var extra_index: usize = extended.operand; + if (small.has_lib_name) extra_index += 1; + if (small.has_align) extra_index += 1; + + const value: DocData.WalkResult = + if (small.has_init) + .{ .void = {} } else .{ .void = {} }; + + return value; + }, .union_decl => { var scope: Scope = .{ .parent = parent_scope, @@ -1887,7 +1954,7 @@ fn collectUnionFieldInfo( @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]) else .void_type; - extra_index += 1; + if (has_type) extra_index += 1; if (has_align) extra_index += 1; if (has_tag) extra_index += 1;