As-Built Documentation

Abstract: What does “as-built documentation” mean? For me, it means being able to find answers to my questions by quickly viewing references in the code. Take a look at how I use as-built documentation in a real-life scenario with Understand.

Most of the time, my internal definition for a given buzzword or catchphrase is: “keyword to obtain money.” What is STEM?  “A word to use to obtain grant money and/or donations” What is organic? “A word attached to food that increases the price.” What is “as-built documentation?” “A catchphrase to get you to invest your money in Understand.”

However, a buzzword or catchphrase is more efficient at obtaining money when it has meaning. What does “as-built documentation” mean? I’m not sure how the sales team defines it, but here’s a use case from my development.

The Understand strict c++ parser uses the llvm library. I needed to modify the strict parser to be able to read files directly from git, not from the disk. The strict parser already provides a virtual file system for the llvm library to handle file encodings, but the status call deferred to the real file system. Because the files exist only in git and not on disk, the real file system can’t find them and the status call results in a file not found error.

In this scenario, “as-built documentation” means instead of trying to find the official llvm documentation, I looked through the references. Here’s the overload for status that delegates to the real file system (it turns out opening the file for reading also delegates to the real file system).

  llvm::ErrorOr<llvm::vfs::Status> status(const Twine &path) override
  {
    if (mCodec || !mCompiler.isEmpty()) {
      // Stat can't be optimized. The file has
      // to be opened and converted to UTF-8.
      if (auto file = openFileForRead(path))
        return (*file)->status();
    }
    return mReal->status(path);
  }

So, the first step is to see what the status function does. Control-Click updates the information browser and previewer.

The pure virtual implementation isn’t immediately helpful. But, one of the overrides starts with “RealFileSystem” so double-clicking on that in the information browser gives:

It looks like the real file system copies an existing status (line 293). Clicking through the other overloads shows most of them delegate to another file system like our code is already doing. So, the next approach is to look directly at the status class with Control+Click.

Scrolling down a little reveals three constructors. Since a valid status doesn’t already exist, only the third constructor matters.

What values should I use for the parameters? Some seem obvious (I know the file name), but I have no idea what the UniqueID is. So, I’ll look through some calls.

The first call reference is not helpful. It’s essentially a copy. Several more are also copies. One useful call is from the InMemoryFileSystem.

It looks like this status has essentially default parameters. So, I can start from this and change the parameters I know. I know the filename. I still don’t know what the UniqueId is, but now I know a function to generate one: getNextVirtualUniqueID(). The timestamp of the git commit is known, but what is a TimePoint object? I could click on the TimePoint class to pull up the class, but I’ve glanced through the calls already and know there’s a useful one:

I can determine the type of the variable ModificationTime by hovering. I know the time_t for my file so I can just pass it to this conversion function. The next two parameters are user and group, but I don’t know those and it looks valid to leave them null. Then is the size, which I do know, so I can update that. Next is the file type. The git file is a file, not a directory. What are the other enum values? I can control+click on directory_file to find the enumerator definition.

So, I’ll replace the directory_file enumerator with the regular_file enumerator to treat the git files as regular files. I can similarly look up the permissions enumerator by using the back button on the previewer and then Control+click all_all. 

I’m not sure if the permissions will matter, but I know writing won’t be supported. So, I’ll update the enumerator to “all_read”. Putting it all together, I can construct a status object if the real file system failed to find the file:

      auto status = mReal->status(path);
      if (!status && file.IsValid()) {
        // file exists virtually, create a status for it
        status = llvm::vfs::Status(path.str().c_str(),
                                   llvm::vfs::getNextVirtualUniqueID(),
                                   llvm::sys::toTimePoint(file.GetTimestamp()),
                                   0, 0, file.GetSize(),
                                   llvm::sys::fs::file_type::regular_file,
                                   llvm::sys::fs::perms::all_read);

      }

Voila, my git files are found. So, what does “as-built documentation” mean? For me, it means being able to find answers to my questions by quickly viewing references in the code. Hopefully, it’s now a better catchphrase to convince you to invest money in Understand.