Page MenuHomePhabricator

[clang-format] Add new option to support adding a space between Javascript Union and Intersection types
AcceptedPublic

Authored by MyDeveloperDay on Jan 13 2022, 12:56 AM.

Details

Summary

https://github.com/llvm/llvm-project/issues/49858

The following issue highlights a problem where we cannot add a space between A|B when detecting a JSTypeOperator

This patch allows clang-format to be configured to support that (which seems to match most references I can find)

https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types
https://flow.org/en/docs/types/intersections/

Fixes: #49858

Diff Detail

Event Timeline

MyDeveloperDay requested review of this revision.Jan 13 2022, 12:56 AM
MyDeveloperDay created this revision.
mprobst added inline comments.Jan 13 2022, 12:59 AM
clang/lib/Format/TokenAnnotator.cpp
3520–3524

shouldn't you change this line here?

MyDeveloperDay added inline comments.Jan 13 2022, 1:11 AM
clang/lib/Format/TokenAnnotator.cpp
3520–3524

You know I thought the same and this was where I first put the code change in, but this code doesn't seem to have any effect and I've been caught out by this before... (anyone else seen that?)

I'm not sure if something has been changed, but I'm finding that often I add code into spaceRequiredBetween() and despite it being executed correctly it doesn't have the desired effect, which is why the code is in spaceRequiredBefore()

mprobst added inline comments.Jan 13 2022, 1:29 AM
clang/lib/Format/TokenAnnotator.cpp
3520–3524

Generally we put space between two operators. So this line must have some effect, as otherwise we'd always emit A | B. Given that, I think we need more debugging here to make this change - working around by some more code somewhere else doesn't seem like a good long term approach.

Also, note that this is all in spaceRequiredBefore, right?

clang/lib/Format/TokenAnnotator.cpp
3475

Be explicit on the binding.

3520–3524

It's on my plan to refactor these 2 methods, because I think they can and should be made easier to understand and reason about.

So from my point of view one can accept this patch.

curdeius accepted this revision.Jan 13 2022, 2:12 AM

LGTM apart from nits.
I agree though that spaceRequired(Before|Between) need some refactoring love.

clang/docs/ReleaseNotes.rst
327

Also, why capital letters on union and intersection type?

clang/include/clang/Format/Format.h
3618
This revision is now accepted and ready to land.Jan 13 2022, 2:12 AM
curdeius added inline comments.Jan 13 2022, 2:17 AM
clang/unittests/Format/FormatTestJS.cpp
1708–1726

Oh, you might need to add a test for this case too.

curdeius requested changes to this revision.Jan 13 2022, 2:27 AM
curdeius added inline comments.
clang/lib/Format/TokenAnnotator.cpp
3520–3526

I modified it like this and it passes all the tests. Please recheck.

This revision now requires changes to proceed.Jan 13 2022, 2:27 AM
mprobst added inline comments.Jan 13 2022, 2:28 AM
clang/lib/Format/TokenAnnotator.cpp
3520–3524

I appreciate the intention to refactor this in the future.

I still believe we really have to understand how this code works though, and why changing this line doesn't have the effect we'd expect, before we land the fix. Chances are there is some substantial misunderstanding how this all fits together, which usually leads to bugs.

curdeius added inline comments.Jan 13 2022, 2:30 AM
clang/unittests/Format/FormatTestJS.cpp
1705–1726

Suggestion.

MyDeveloperDay added inline comments.Jan 13 2022, 5:54 AM
clang/lib/Format/TokenAnnotator.cpp
3520–3524

@mprobst I do agree, let me take another look.

MyDeveloperDay marked 10 inline comments as done.

Make suggested improvements
Add additional test case

mprobst added inline comments.Jan 14 2022, 1:21 AM
clang/lib/Format/TokenAnnotator.cpp
3522

Why do we need this further qualification here? I'd have expect that you can simply "return Style.SpacesInJavaScriptUnion;"? identifier || template closer also sounds oddly specific, why exactly those?

MyDeveloperDay added inline comments.Jan 14 2022, 7:53 AM
clang/lib/Format/TokenAnnotator.cpp
3522

Left = template closer, Right =JsTypeOperator is for this case

type Foo = Bar<X> | Baz;
               ^^^^^

Left = type or identifier, Right =JsTypeOperator is for this case

let x: A | B = A | B;
    ^^^^^^^^^
curdeius accepted this revision.Jan 14 2022, 7:55 AM

Looks ok from my side.

This revision is now accepted and ready to land.Jan 14 2022, 7:55 AM
mprobst added inline comments.Jan 14 2022, 8:42 AM
clang/lib/Format/TokenAnnotator.cpp
3522

What about:

let x: {foo: string}&{bar: number};

I'm not sure including curlies would be comprehensive. It might be worth checking the TS grammar.

But coming back, did you try this:

if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator)) {
  return Style.SpacesInJavaScriptUnion;

(We might also need to do something in spaceRequiredBefore, maybe that fires earlier?)