authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2022-03-11 18:26:21+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 19:10:11-07:00
logec7f4d1faab8aa9b797f96d233d2ca12c99d2179
tree5b942af287986be24b342f30fce1c1cbbbb996c6
parentd745dde54f00ee882010e681d364283f0c6f045a

autodoc: add support for anytype and improve semantics for array length


2 files changed, 188 insertions(+), 78 deletions(-)

lib/docs/main.js+112-69
...@@ -187,7 +187,7 @@...@@ -187,7 +187,7 @@
187 i += 1;187 i += 1;
188 console.assert(isDecl(decl));188 console.assert(isDecl(decl));
189 if ("type" in decl.value) {189 if ("type" in decl.value) {
190 return typeTypeId;190 return { type: typeTypeId };
191 }191 }
192192
193 if ("declPath" in decl.value) {193 if ("declPath" in decl.value) {
...@@ -232,6 +232,10 @@...@@ -232,6 +232,10 @@
232 return fn_type.ret;232 return fn_type.ret;
233 }233 }
234234
235 if ("void" in decl.value) {
236 return { type: typeTypeId };
237 }
238
235 console.log("TODO: handle in `typeOfDecl` more cases: ", decl);239 console.log("TODO: handle in `typeOfDecl` more cases: ", decl);
236 console.assert(false);240 console.assert(false);
237 throw {};241 throw {};
...@@ -472,22 +476,9 @@...@@ -472,22 +476,9 @@
472 var html = '<pre>' + escapeHtml(fieldNode.name) + ": ";476 var html = '<pre>' + escapeHtml(fieldNode.name) + ": ";
473 if (isVarArgs && i === typeObj.params.length - 1) {477 if (isVarArgs && i === typeObj.params.length - 1) {
474 html += '...';478 html += '...';
475 } else if ("declRef" in value) {
476 var decl = zigAnalysis.decls[value.declRef];
477 var val = resolveValue(decl.value);
478 var valType = zigAnalysis.types[argTypeIndex];
479
480 var valTypeName = typeShorthandName(valType);
481
482 html += '<a href="'+navLinkDecl(decl.name)+'">';
483 html += '<span class="tok-kw" style="color:lightblue;">' + escapeHtml(decl.name) + '</span>';
484 html += '</a>';
485 html += ' ('+ valTypeName +')';
486 } else if ("type" in value) {
487 var name = zigAnalysis.types[value.type].name;
488 html += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
489 } else {479 } else {
490 html += '<span class="tok-kw">var</span>';480 var name = typeValueName(value);
481 html += '<span class="tok-kw">' + name + '</span>';
491 }482 }
492483
493 html += ',</pre>';484 html += ',</pre>';
...@@ -657,24 +648,52 @@...@@ -657,24 +648,52 @@
657 }648 }
658649
659 function typeValueName(typeValue, wantHtml, wantLink, fnDecl, linkFnNameDecl) {650 function typeValueName(typeValue, wantHtml, wantLink, fnDecl, linkFnNameDecl) {
660 if ("declPath" in typeValue) {651
661 if (typeValue.hasCte) {652 if ("int" in typeValue) {
662 // TODO: find the cte, print it nicely653 return typeValue.int.value;
663 if (wantLink) {654 }
664 return '<a href="">[ComptimeExpr]</a>';655 if ("call" in typeValue) {
665 } else {656 var result = "";
666 return "[ComptimeExpr]";657 var call = zigAnalysis.calls[typeValue.call];
667 }658 var functionName = typeValueName(call.func);
668 }659 result += functionName + "(";
669 var declIndex = typeValue.declPath[0];660 for (var j = 0; j < call.args.length; j += 1) {
670 var name = zigAnalysis.decls[declIndex].name;661 result += typeValueName(call.args[j]);
671 var declPath = getCanonDeclPath(declIndex);662 if (j != call.args.length -1) result += ",";
672 if (wantLink) {
673 var nl = navLink(declPath.pkgNames, declPath.declNames);
674 return '<a href="' + nl + '">' + name + '</a>';
675 } else {
676 return name;
677 }663 }
664
665 return result + ")";
666 }
667 if ("comptimeExpr" in typeValue) {
668 return "[ComptimeExpr]";
669 }
670 if ("declPath" in typeValue) {
671 var result = "";
672 for (var j = typeValue.declPath.length - 1; j >= 0; j--) {
673 var decl = zigAnalysis.decls[typeValue.declPath[j]];
674
675 // TODO: handle nested decl paths properly!
676 if (typeValue.hasCte) {
677 if (wantHtml)
678 result += "<a href=\"\">[ComptimeExpr]</a>";
679 else
680 result += "[ComptimeExpr]";
681 break;
682 }
683 var name = escapeHtml(decl.name);
684 if (wantHtml) {
685 result += '<a href="'+navLinkDecl(decl.name)+'">';
686 result += '<span class="tok-kw" style="color:lightblue;">' +
687 name + '</span>';
688 result += '</a>';
689 } else {
690 result += name;
691 }
692
693 if (j != 0) result += ".";
694 }
695
696 return result;
678 }697 }
679698
680 console.assert("type" in typeValue)699 console.assert("type" in typeValue)
...@@ -760,10 +779,11 @@...@@ -760,10 +779,11 @@
760 switch (typeObj.kind) {779 switch (typeObj.kind) {
761 case typeKinds.Array:780 case typeKinds.Array:
762 var name = "[";781 var name = "[";
782 var lenName = typeValueName(typeObj.len, wantHtml);
763 if (wantHtml) {783 if (wantHtml) {
764 name += '<span class="tok-number">' + typeObj.len + '</span>';784 name += '<span class="tok-number">' + lenName + '</span>';
765 } else {785 } else {
766 name += typeObj.len;786 name += lenName;
767 }787 }
768 name += "]";788 name += "]";
769 name += typeValueName(typeObj.child, wantHtml, wantSubLink, null);789 name += typeValueName(typeObj.child, wantHtml, wantSubLink, null);
...@@ -986,12 +1006,16 @@...@@ -986,12 +1006,16 @@
986 } else {1006 } else {
987 var decl = zigAnalysis.decls[value.declPath[0]];1007 var decl = zigAnalysis.decls[value.declPath[0]];
988 var val = resolveValue(decl.value);1008 var val = resolveValue(decl.value);
989 var valType = zigAnalysis.types[argTypeIndex];1009 if ("comptimeExpr" in val) {
9901010 payloadHtml += "[ComptimeExpr]";
991 var valTypeName = typeShorthandName(valType);1011 } else {
992 payloadHtml += '<a href="'+navLinkDecl(decl.name)+'">';1012 console.assert("type" in val);
993 payloadHtml += '<span class="tok-kw" style="color:lightblue;">' + escapeHtml(decl.name) + '</span>';1013 var valType = zigAnalysis.types[val.type];
994 payloadHtml += '</a>';1014 var valTypeName = typeShorthandName(valType);
1015 payloadHtml += '<a href="'+navLinkDecl(decl.name)+'">';
1016 payloadHtml += '<span class="tok-kw" style="color:lightblue;">' + escapeHtml(decl.name) + '</span>';
1017 payloadHtml += '</a>';
1018 }
995 }1019 }
996 } else if ("type" in value) {1020 } else if ("type" in value) {
997 var name = typeValueName(value, false);1021 var name = typeValueName(value, false);
...@@ -1258,6 +1282,43 @@...@@ -1258,6 +1282,43 @@
1258 }1282 }
1259 }1283 }
1260 }1284 }
1285
1286 declLen = container.privDecls ? container.privDecls.length : 0;
1287 for (var i = 0; i < declLen; i += 1) {
1288 var decl = zigAnalysis.decls[container.privDecls[i]];
1289 var declValue = resolveValue(decl.value);
1290
1291 if (decl.kind === 'var') {
1292 varsList.push(decl);
1293 continue;
1294 }
1295
1296 if (decl.kind === 'const') {
1297 if (!("type" in declValue)){
1298 valsList.push(decl);
1299 } else {
1300 var value = zigAnalysis.types[declValue.type];
1301 var kind = value.kind;
1302 if (kind === typeKinds.Fn) {
1303 // TODO: handle CTE return types when we know their type.
1304 const resVal = resolveValue(value.ret);
1305 if ("type" in resVal && resVal.type == typeTypeId) {
1306 typesList.push(decl);
1307 } else {
1308 fnsList.push(decl);
1309 }
1310
1311 } else if (typeIsErrSet(declValue.type)) {
1312 errSetsList.push(decl);
1313 } else if (typeIsStructWithNoFields(declValue.type)) {
1314 namespacesList.push(decl);
1315 } else {
1316 typesList.push(decl);
1317 }
1318 }
1319 }
1320 }
1321
1261 typesList.sort(byNameProperty);1322 typesList.sort(byNameProperty);
1262 namespacesList.sort(byNameProperty);1323 namespacesList.sort(byNameProperty);
1263 errSetsList.sort(byNameProperty);1324 errSetsList.sort(byNameProperty);
...@@ -1349,35 +1410,9 @@...@@ -1349,35 +1410,9 @@
1349 html += ": ";1410 html += ": ";
1350 if (field.failure === true) {1411 if (field.failure === true) {
1351 html += '<span class="tok-kw" style="color:red;">#FAILURE#</span>';1412 html += '<span class="tok-kw" style="color:red;">#FAILURE#</span>';
1352 } else if ("declPath" in field) {
1353 for (var j = field.declPath.length - 1; j >= 0; j--) {
1354 var decl = zigAnalysis.decls[field.declPath[j]];
1355
1356 // TODO: handle nested decl paths properly!
1357 if (field.hasCte) {
1358 html += "<a href=\"\">[ComptimeExpr]</a>";
1359 break;
1360 }
1361
1362 html += '<a href="'+navLinkDecl(decl.name)+'">';
1363 html += '<span class="tok-kw" style="color:lightblue;">' +
1364 escapeHtml(decl.name) + '</span>';
1365 html += '</a>';
1366 if (j != 0) html += ".";
1367 }
1368 // at the end of the for loop this is the value of `decl`
1369 //decl = zigAnalysis.decls[field.declPath[0]];
1370
1371 var val = resolveValue(decl.value);
1372 console.assert("type" in val);
1373 var valType = zigAnalysis.types[val.type];
1374 var valTypeName = typeShorthandName(valType);
1375 html += ' ('+ valTypeName +')';
1376 } else if ("type" in field) {
1377 var name = zigAnalysis.types[field.type].name;
1378 html += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
1379 } else {1413 } else {
1380 html += '<span class="tok-kw">var</span>';1414 var name = typeValueName(field);
1415 html += '<span class="tok-kw">'+ name +'</span>';
1381 }1416 }
1382 }1417 }
13831418
...@@ -1544,6 +1579,14 @@...@@ -1544,6 +1579,14 @@
1544 return childDecl;1579 return childDecl;
1545 }1580 }
1546 }1581 }
1582 if (!parentType.privDecls) return null;
1583 for (var i = 0; i < parentType.privDecls.length; i += 1) {
1584 var declIndex = parentType.privDecls[i];
1585 var childDecl = zigAnalysis.decls[declIndex];
1586 if (childDecl.name === childName) {
1587 return childDecl;
1588 }
1589 }
1547 return null;1590 return null;
1548 }1591 }
15491592
src/Autodoc.zig+76-9
...@@ -92,7 +92,15 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -92,7 +92,15 @@ pub fn generateZirData(self: *Autodoc) !void {
92 // instead of just assinging "array" to them.92 // instead of just assinging "array" to them.
93 break :blk .{93 break :blk .{
94 .Array = .{94 .Array = .{
95 .len = 1,95 .len = .{
96 .int = .{
97 .typeRef = .{
98 .type = @enumToInt(Ref.usize_type),
99 },
100 .value = 1,
101 .negated = false,
102 },
103 },
96 .child = .{ .type = 0 },104 .child = .{ .type = 0 },
97 },105 },
98 };106 };
...@@ -374,7 +382,7 @@ const DocData = struct {...@@ -374,7 +382,7 @@ const DocData = struct {
374 child: TypeRef,382 child: TypeRef,
375 },383 },
376 Array: struct {384 Array: struct {
377 len: usize,385 len: WalkResult,
378 child: TypeRef,386 child: TypeRef,
379 },387 },
380 Struct: struct {388 Struct: struct {
...@@ -516,6 +524,7 @@ const DocData = struct {...@@ -516,6 +524,7 @@ const DocData = struct {
516 /// An example of indidirectness is `const bar = foo;`.524 /// An example of indidirectness is `const bar = foo;`.
517 const TypeRef = union(enum) {525 const TypeRef = union(enum) {
518 unspecified,526 unspecified,
527 @"anytype",
519 declPath: DeclPath,528 declPath: DeclPath,
520 type: usize, // index in `types`529 type: usize, // index in `types`
521 comptimeExpr: usize, // index in `comptimeExprs`530 comptimeExpr: usize, // index in `comptimeExprs`
...@@ -530,10 +539,10 @@ const DocData = struct {...@@ -530,10 +539,10 @@ const DocData = struct {
530 w: anytype,539 w: anytype,
531 ) !void {540 ) !void {
532 switch (self) {541 switch (self) {
533 .unspecified => {542 .unspecified, .@"anytype" => {
534 try w.print(543 try w.print(
535 \\{{ "unspecified":{{}} }}544 \\{{ "{s}":{{}} }}
536 , .{});545 , .{@tagName(self)});
537 },546 },
538547
539 .type, .comptimeExpr, .call => |v| {548 .type, .comptimeExpr, .call => |v| {
...@@ -566,6 +575,7 @@ const DocData = struct {...@@ -566,6 +575,7 @@ const DocData = struct {
566 @"undefined": TypeRef,575 @"undefined": TypeRef,
567 @"struct": Struct,576 @"struct": Struct,
568 bool: bool,577 bool: bool,
578 @"anytype",
569 type: usize, // index in `types`579 type: usize, // index in `types`
570 declPath: DeclPath,580 declPath: DeclPath,
571 int: struct {581 int: struct {
...@@ -600,7 +610,7 @@ const DocData = struct {...@@ -600,7 +610,7 @@ const DocData = struct {
600 w: anytype,610 w: anytype,
601 ) !void {611 ) !void {
602 switch (self) {612 switch (self) {
603 .void, .@"unreachable" => {613 .void, .@"unreachable", .@"anytype" => {
604 try w.print(614 try w.print(
605 \\{{ "{s}":{{}} }}615 \\{{ "{s}":{{}} }}
606 , .{@tagName(self)});616 , .{@tagName(self)});
...@@ -755,6 +765,13 @@ fn walkInstruction(...@@ -755,6 +765,13 @@ fn walkInstruction(
755 },765 },
756 };766 };
757 },767 },
768 .error_union_type => {
769 const pl_node = data[inst_index].pl_node;
770 const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index);
771
772 // TODO: return the actual error union instread of cheating
773 return self.walkRef(file, parent_scope, extra.data.rhs);
774 },
758 .ptr_type_simple => {775 .ptr_type_simple => {
759 const ptr = data[inst_index].ptr_type_simple;776 const ptr = data[inst_index].ptr_type_simple;
760 const type_slot_index = self.types.items.len;777 const type_slot_index = self.types.items.len;
...@@ -768,6 +785,20 @@ fn walkInstruction(...@@ -768,6 +785,20 @@ fn walkInstruction(
768785
769 return DocData.WalkResult{ .type = type_slot_index };786 return DocData.WalkResult{ .type = type_slot_index };
770 },787 },
788 .array_type => {
789 const bin = data[inst_index].bin;
790 const len = try self.walkRef(file, parent_scope, bin.lhs);
791 const child = walkResultToTypeRef(try self.walkRef(file, parent_scope, bin.rhs));
792
793 const type_slot_index = self.types.items.len;
794 try self.types.append(self.arena, .{
795 .Array = .{
796 .len = len,
797 .child = child,
798 },
799 });
800 return DocData.WalkResult{ .type = type_slot_index };
801 },
771 .array_init => {802 .array_init => {
772 const pl_node = data[inst_index].pl_node;803 const pl_node = data[inst_index].pl_node;
773 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);804 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
...@@ -780,7 +811,13 @@ fn walkInstruction(...@@ -780,7 +811,13 @@ fn walkInstruction(
780 const type_slot_index = self.types.items.len;811 const type_slot_index = self.types.items.len;
781 try self.types.append(self.arena, .{812 try self.types.append(self.arena, .{
782 .Array = .{813 .Array = .{
783 .len = operands.len,814 .len = .{
815 .int = .{
816 .typeRef = .{ .type = @enumToInt(Ref.usize_type) },
817 .value = operands.len,
818 .negated = false,
819 },
820 },
784 .child = typeOfWalkResult(array_data[0]),821 .child = typeOfWalkResult(array_data[0]),
785 },822 },
786 });823 });
...@@ -1017,6 +1054,23 @@ fn walkInstruction(...@@ -1017,6 +1054,23 @@ fn walkInstruction(
1017 .{@tagName(tags[param_index])},1054 .{@tagName(tags[param_index])},
1018 );1055 );
1019 },1056 },
1057 .param_anytype => {
1058 // TODO: where are the doc comments?
1059 const str_tok = data[param_index].str_tok;
1060
1061 const name = str_tok.get(file.zir);
1062
1063 param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);
1064 self.ast_nodes.appendAssumeCapacity(.{
1065 .name = name,
1066 .docs = "",
1067 .@"comptime" = true,
1068 });
1069
1070 param_type_refs.appendAssumeCapacity(
1071 DocData.TypeRef{ .@"anytype" = {} },
1072 );
1073 },
1020 .param, .param_comptime => {1074 .param, .param_comptime => {
1021 const pl_tok = data[param_index].pl_tok;1075 const pl_tok = data[param_index].pl_tok;
1022 const extra = file.zir.extraData(Zir.Inst.Param, pl_tok.payload_index);1076 const extra = file.zir.extraData(Zir.Inst.Param, pl_tok.payload_index);
...@@ -1024,10 +1078,11 @@ fn walkInstruction(...@@ -1024,10 +1078,11 @@ fn walkInstruction(
1024 file.zir.nullTerminatedString(extra.data.doc_comment)1078 file.zir.nullTerminatedString(extra.data.doc_comment)
1025 else1079 else
1026 "";1080 "";
1081 const name = file.zir.nullTerminatedString(extra.data.name);
10271082
1028 param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);1083 param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);
1029 self.ast_nodes.appendAssumeCapacity(.{1084 self.ast_nodes.appendAssumeCapacity(.{
1030 .name = file.zir.nullTerminatedString(extra.data.name),1085 .name = name,
1031 .docs = doc_comment,1086 .docs = doc_comment,
1032 .@"comptime" = tags[param_index] == .param_comptime,1087 .@"comptime" = tags[param_index] == .param_comptime,
1033 });1088 });
...@@ -1094,6 +1149,18 @@ fn walkInstruction(...@@ -1094,6 +1149,18 @@ fn walkInstruction(
1094 .{@tagName(extended.opcode)},1149 .{@tagName(extended.opcode)},
1095 );1150 );
1096 },1151 },
1152 .variable => {
1153 const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small);
1154 var extra_index: usize = extended.operand;
1155 if (small.has_lib_name) extra_index += 1;
1156 if (small.has_align) extra_index += 1;
1157
1158 const value: DocData.WalkResult =
1159 if (small.has_init)
1160 .{ .void = {} } else .{ .void = {} };
1161
1162 return value;
1163 },
1097 .union_decl => {1164 .union_decl => {
1098 var scope: Scope = .{1165 var scope: Scope = .{
1099 .parent = parent_scope,1166 .parent = parent_scope,
...@@ -1887,7 +1954,7 @@ fn collectUnionFieldInfo(...@@ -1887,7 +1954,7 @@ fn collectUnionFieldInfo(
1887 @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index])1954 @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index])
1888 else1955 else
1889 .void_type;1956 .void_type;
1890 extra_index += 1;1957 if (has_type) extra_index += 1;
18911958
1892 if (has_align) extra_index += 1;1959 if (has_align) extra_index += 1;
1893 if (has_tag) extra_index += 1;1960 if (has_tag) extra_index += 1;