Skip to content

Migrate all 3C JSON generation to use the LLVM JSON library #620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mattmccutchen-cci opened this issue Jun 19, 2021 · 0 comments
Open
Labels

Comments

@mattmccutchen-cci
Copy link
Member

We should migrate all 3C code that generates JSON to use the LLVM JSON library rather than manual string concatenation, which is prone to bugs like #605 and #619.

The main decision we need to make is which version of the LLVM JSON API is most suitable for our purpose. If I understand correctly, our options are (from lowest to highest level):

  1. llvm::json::OStream begin/end. Example from the API documentation:
    /// json::OStream J(OS);
    // J.arrayBegin();
    /// for (const Event &E : Events) {
    /// J.objectBegin();
    /// J.attribute("timestamp", int64_t(E.Time));
    /// J.attributeBegin("participants");
    /// for (const Participant &P : E.Participants)
    /// J.value(P.toString());
    /// J.attributeEnd();
    /// J.objectEnd();
    /// }
    /// J.arrayEnd();
  2. llvm::json::OStream lambda. Example from the API documentation:
    /// json::OStream J(OS);
    /// J.array([&]{
    /// for (const Event &E : Events)
    /// J.object([&] {
    /// J.attribute("timestamp", int64_t(E.Time));
    /// J.attributeArray("participants", [&] {
    /// for (const Participant &P : E.Participants)
    /// J.value(P.toString());
    /// });
    /// });
    /// });
  3. Constructing an llvm::json::Value that we can ultimately send to an output stream with <<. One example from clangd (there are many other examples in the same file demonstrating different things):
    llvm::json::Object Diag{
    {"range", D.range},
    {"severity", D.severity},
    {"message", D.message},
    };
    if (D.category)
    Diag["category"] = *D.category;
    if (D.codeActions)
    Diag["codeActions"] = D.codeActions;
    if (!D.code.empty())
    Diag["code"] = D.code;
    if (!D.source.empty())
    Diag["source"] = D.source;
    if (D.relatedInformation)
    Diag["relatedInformation"] = *D.relatedInformation;

The style of our existing code is most similar to (1), but I'm guessing that was only because we didn't want to do the work to introduce the abstractions needed for (2) or (3), not because we thought they would be bad. Migrating to (2) or (3) would mean more churn now but may make the code much easier to maintain in the long run.

Currently, a bunch of 3C objects have a T::dumpJson(llvm::raw_ostream &) method. Obviously, we'll have to change the interface of that method so that it can run in the middle of the dumping of a larger object via whichever JSON API version we choose. If we use version (3) and are willing to move to the JSON library's standard interface, which is a non-member function llvm::json::Value toJSON(const T &), then the llvm::json::Value constructor will call the toJSON function on sub-objects implicitly for us, rather than us having to explicitly call our own function (dumpJson or whatever we name it). The clangd example above is using toJSON; if it didn't, it would have to do something like Diag["codeActions"] = D.codeActions.dumpJson(), etc.

If we don't foresee JSON output becoming a performance bottleneck anytime soon, I think we're probably best served by migrating all the way to (3) with toJSON, but I'd welcome other thoughts.

mattmccutchen-cci added a commit that referenced this issue Jun 19, 2021
Windows.

Other escaping bugs may remain; #620 is to fix all of them.

Fixes #619.
mattmccutchen-cci added a commit that referenced this issue Jun 19, 2021
Windows.

Other escaping bugs may remain; #620 is to fix all of them.

Fixes #619.
mattmccutchen-cci added a commit that referenced this issue Jun 19, 2021
Windows.

Other escaping bugs may remain; #620 is to fix all of them.

Fixes #619.
mattmccutchen-cci added a commit that referenced this issue Jun 19, 2021
Windows.

Other escaping bugs may remain; #620 is to fix all of them.

Fixes #619.
mattmccutchen-cci added a commit that referenced this issue Jun 21, 2021
Windows.

Other escaping bugs may remain; #620 is to fix all of them.

Fixes #619.
mattmccutchen-cci added a commit that referenced this issue Jun 22, 2021
Windows.

Other escaping bugs may remain; #620 is to fix all of them.

Fixes #619.
mattmccutchen-cci added a commit that referenced this issue Jun 23, 2021
…indows. (#626)

* Fix escaping bugs that currently affect the JSON formatting test on
Windows.

Other escaping bugs may remain; #620 is to fix all of them.

Fixes #619.

* Add test of a backslash in a file path on Linux and Mac OS X.

While I'm here, fix a typo in the name of json_formating.c and add `--`
to its `3c` command lines.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant