This is an archive of the discontinued LLVM Phabricator instance.

clang-format: [JS] handle "off" in imports
ClosedPublic

Authored by mprobst on Apr 29 2021, 2:38 AM.

Details

Summary

Previously, the JavaScript import sorter would ignore `// clang-format
off` and on comments. This change fixes that. It tracks whether
formatting is enabled for a stretch of imports, and then only sorts and
merges the imports where formatting is enabled, in individual chunks.

This means that there's no meaningful total order when module references are mixed
with blocks that have formatting disabled. The alternative approach
would have been to sort all imports that have formatting enabled in one
group. However that raises the question where to insert the
formatting-off block, which can also impact symbol visibility (in
particular for exports). In practice, sorting in chunks probably isn't a
big problem.

This change also simplifies the general algorithm: instead of tracking
indices separately and sorting them, it just sorts the vector of module
references. And instead of attempting to do fine grained tracking of
whether the code changed order, it just prints out the module references
text, and compares that to the previous text. Given that source files
typically have dozens, but not even hundreds of imports, the performance
impact seems negligible.

Diff Detail

Event Timeline

mprobst requested review of this revision.Apr 29 2021, 2:38 AM
mprobst created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptApr 29 2021, 2:38 AM
h-joo added inline comments.Apr 29 2021, 2:10 PM
clang/lib/Format/SortJavaScriptImports.cpp
252

References seem read-only. Can you make it const Smallvector &?

257

nit : Start

379

I think this has a potential bug that if the user makes

// clang-format off
// clang-format on

Every subsequent import will fail to be sorted.

or maybe something like below

//clang-format off
import {A, B} from "./a"
//clang-format on
//clang-format off

will make the 'should not be sorted' part of the code be sorted.

Even if this is not the case, could you write a test for this one?

clang/unittests/Format/SortImportsTestJS.cpp
405

Do you think it makes sense to add some weird test cases that // clang-format on-off switch, is pointless or ill-formed?
examples :

// this is for the corner-case I mentioned above around the comment token handler
// clang-format off
// clang-format on
import {C} from "./.."
import {B} from "./.."
import {A} from "./.."
// The clang-format off comment might be dropped or not?
// clang-format on
import {C} from "./.."
import {B} from "./.."
import {A} from "./.."
// clang-format off
// This test maybe isn't necessary?
// clang-format off
// clang-format off
import {C} from "./.."
import {B} from "./.."
import {A} from "./.."

...and maybe some other fun examples! :)

krasimir added inline comments.Apr 29 2021, 2:18 PM
clang/lib/Format/SortJavaScriptImports.cpp
157–158

nit: capitalize, I, E (:

191
251

We should pass in and return llvm::SmallVectorImpl<JsModuleReference> (the size version is mainly for local vars). Also, take the arg by const reference.

257

nit: Start

288

use llvm::SmallVectorImpl<JsModuleReference>

clang/unittests/Format/SortImportsTestJS.cpp
362

Was this change intended? It doesn't seem related to this patch.

385

can we have a test that checks that we don't merge import lines in an off section

@h-joo , seems we had a comment race :D cheers!

h-joo requested changes to this revision.Apr 30 2021, 12:26 AM

@h-joo , seems we had a comment race :D cheers!

:D

This revision now requires changes to proceed.Apr 30 2021, 12:26 AM
mprobst marked 9 inline comments as done.Apr 30 2021, 2:32 AM

PTAL, addressed review comments.

clang/lib/Format/SortJavaScriptImports.cpp
191

We don't in the C++ import sorter. Sigh.

I think the Real Fix (tm) would be folding the clang-format off thing in import sorting with affected lines, wouldn't it? I don't quite know how to untangle this, but it seems suboptimal that each sorter here re-implements the same logic.

251

That gives me:

error: no viable conversion from 'SmallVector<[...], 16>' to 'const SmallVector<[...], (default) CalculateSmallVectorDefaultInlinedElements<T>::value aka 1>'

288

As above, this seems not possible.

379

Nice, good catch! Done.

clang/unittests/Format/SortImportsTestJS.cpp
362

the empty line is intended. Previously this wouldn't end up formatting because the code was trying to be too clever in detecting changes.

mprobst updated this revision to Diff 341814.Apr 30 2021, 2:33 AM
mprobst marked 4 inline comments as done.
  • review comments
mprobst updated this revision to Diff 341815.Apr 30 2021, 2:33 AM
  • test for avoiding merges
mprobst marked an inline comment as done.Apr 30 2021, 2:34 AM

added test for merging

h-joo accepted this revision.Apr 30 2021, 2:51 AM

LGTM :)

This revision is now accepted and ready to land.Apr 30 2021, 2:51 AM
krasimir accepted this revision.Apr 30 2021, 4:00 AM
krasimir added inline comments.
clang/lib/Format/SortJavaScriptImports.cpp
257

please fix lint warning on line 257

mprobst updated this revision to Diff 341849.Apr 30 2021, 5:16 AM
  • review comments
mprobst marked an inline comment as done.Apr 30 2021, 5:16 AM
This revision was landed with ongoing or failed builds.Apr 30 2021, 5:19 AM
This revision was automatically updated to reflect the committed changes.