Commit ec7f4d1faa

Loris Cro <kappaloris@gmail.com>
2022-03-11 18:26:21
autodoc: add support for anytype and improve semantics for array length
1 parent d745dde
Changed files (2)
lib
docs
src
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 = '<pre>' + 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 += '<a href="'+navLinkDecl(decl.name)+'">';
-                html += '<span class="tok-kw" style="color:lightblue;">' + escapeHtml(decl.name) + '</span>';
-                html += '</a>';
-                html += ' ('+ valTypeName +')';
-            } else if ("type" in value) {
-                var name = zigAnalysis.types[value.type].name;
-                html += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
             } else {
-                html += '<span class="tok-kw">var</span>';
+                var name = typeValueName(value);
+                html += '<span class="tok-kw">' + name + '</span>';
             }
 
             html += ',</pre>';
@@ -657,24 +648,52 @@
     }
 
     function typeValueName(typeValue, wantHtml, wantLink, fnDecl, linkFnNameDecl) {
-        if ("declPath" in typeValue) {
-            if (typeValue.hasCte) {
-                // TODO: find the cte, print it nicely
-                if (wantLink) {
-                    return '<a href="">[ComptimeExpr]</a>';
-                } 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 '<a href="' + nl + '">' + name + '</a>';
-            } else {
-                return name;
+
+        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) {
+              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 += "<a href=\"\">[ComptimeExpr]</a>";
+                      else
+                          result += "[ComptimeExpr]";
+                      break;
+                  }
+                  var name = escapeHtml(decl.name);
+                  if (wantHtml) {
+                      result += '<a href="'+navLinkDecl(decl.name)+'">';
+                      result += '<span class="tok-kw" style="color:lightblue;">' +
+                           name + '</span>';
+                      result += '</a>';
+                  } 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 += '<span class="tok-number">' + typeObj.len + '</span>';
+                    name += '<span class="tok-number">' + lenName + '</span>';
                 } 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 += '<a href="'+navLinkDecl(decl.name)+'">';
-                                    payloadHtml += '<span class="tok-kw" style="color:lightblue;">' + escapeHtml(decl.name) + '</span>';
-                                    payloadHtml += '</a>';
+                                    if ("comptimeExpr" in val) {
+                                        payloadHtml += "[ComptimeExpr]";
+                                    } else {
+                                      console.assert("type" in val);
+                                      var valType = zigAnalysis.types[val.type];
+                                      var valTypeName = typeShorthandName(valType);
+                                      payloadHtml += '<a href="'+navLinkDecl(decl.name)+'">';
+                                      payloadHtml += '<span class="tok-kw" style="color:lightblue;">' + escapeHtml(decl.name) + '</span>';
+                                      payloadHtml += '</a>';
+                                    }
                                 }
                             } 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 += '<span class="tok-kw" style="color:red;">#FAILURE#</span>';
-                    } 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 += "<a href=\"\">[ComptimeExpr]</a>";
-                                break;
-                            }
-
-                            html += '<a href="'+navLinkDecl(decl.name)+'">';
-                            html += '<span class="tok-kw" style="color:lightblue;">' +
-                                escapeHtml(decl.name) + '</span>';
-                            html += '</a>';
-                            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 += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
                     } else {
-                        html += '<span class="tok-kw">var</span>';
+                        var name = typeValueName(field);
+                        html += '<span class="tok-kw">'+ name +'</span>';
                     }
                 }
 
@@ -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;
     }
 
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;