@@ -4,7 +4,7 @@ Author: Bob Nystrom
4
4
5
5
Status: Accepted
6
6
7
- Version 0.4 (see [ CHANGELOG] ( #CHANGELOG ) at end)
7
+ Version 0.5 (see [ CHANGELOG] ( #CHANGELOG ) at end)
8
8
9
9
Experiment flag: unquoted-imports
10
10
@@ -341,20 +341,80 @@ after the directives outside of the path. These are all valid:
341
341
342
342
``` dart
343
343
import /* Weird but OK. */ some/path;
344
- export some/path; // Hi there.
345
- part some/path // Before the semicolon? Really?
344
+ import some/path; // Hi there.
345
+ export some/path // Before the semicolon? Really?
346
346
;
347
347
```
348
348
349
349
The syntax that results from the above few sections is simple to tokenize and
350
350
parse while looking like a single opaque "unquoted string" to users and tools.
351
351
352
+ ### Part of directives
353
+
354
+ In Dart today, ` part of ` directives can already contain unquoted dotted
355
+ identifiers, like:
356
+
357
+ ``` dart
358
+ // some_lib.dart
359
+ library some.lib;
360
+
361
+ part 'some_part.dart';
362
+
363
+ // some_part.dart
364
+ part of some.lib;
365
+ ```
366
+
367
+ This is a legacy syntax from when library names were more widely used in Dart.
368
+ Library names in ` part of ` directives have been deprecated for many years
369
+ because the syntax doesn't work well with many tools. How is a given tool
370
+ supposed to know where to find the library that happens to contain a ` library `
371
+ directive with that name? The quoted URI syntax was added later specifically to
372
+ address that point and users are encouraged by documentation and lints to use
373
+ the quoted syntax.
374
+
375
+ Looking at a corpus of 122,420 files:
376
+
377
+ ```
378
+ -- Directive (443733 total) --
379
+ 352744 ( 79.495%): import =========================================
380
+ 55471 ( 12.501%): export =======
381
+ 17823 ( 4.017%): part ===
382
+ 17695 ( 3.988%): part of ===
383
+ ```
384
+
385
+ So ` part of ` directives are fairly rare to begin with. Of them, most use the
386
+ recommended URI syntax and would not be affected by this change:
387
+
388
+ ```
389
+ -- Part of (17695 total) --
390
+ 13229 ( 74.761%): uri ===================================
391
+ 4466 ( 25.239%): library name ============
392
+ ```
393
+
394
+ If we reinterpreted that existing syntax to refer to another package instead of
395
+ a library within the current package, user breakage is likely and would be very
396
+ confusing.
397
+
398
+ To avoid potential user confusion and breakage, the new syntax in this proposal
399
+ isn't allowed in ` part or ` or ` part ` directives. We disallow it in ` part of `
400
+ to avoid confusion with the legacy syntax, and we disallow it in ` part ` to be
401
+ symmetric with ` part of ` .
402
+
403
+ Further, we make a ** language-versioned breaking change** and remove support for
404
+ unquoted library identifiers in ` part of ` directives completely. That way, a
405
+ user never sees syntax in a ` part of ` file that * looks* like a package path but
406
+ means something else.
407
+
408
+ * Since part files should realistically always be part of the same package that
409
+ contains the library that owns them, the new unquoted syntax is of limited use
410
+ for part files anyway. Quoted relative URIs are shorter and more idiomatic.*
411
+
352
412
## Syntax
353
413
354
414
The normative stuff starts now. Here is the proposal:
355
415
356
- We add a new rule and hang it off the existing ` uri ` rule already used by import
357
- and export directives :
416
+ We replace the existing ` uri ` rule with the following rule along with a couple
417
+ of helper rules :
358
418
359
419
```
360
420
uri ::= stringLiteral | packagePath
@@ -371,22 +431,33 @@ between any of the `segmentComponent`, `/`, or `.` tokens in a `packagePath`.
371
431
* In other words, there can be nothing except the terminals themselves from the
372
432
first ` segmentComponent ` in the ` packagePath ` to the last.*
373
433
374
- * An import, export, or part directive can continue to use a ` stringLiteral ` for
375
- the quoted form (which is what they will do for relative references). But they
376
- can also use a ` packagePath ` , which is a slash-separated series of segments,
377
- each of which is a series of dot-separated components.*
434
+ * An import or export directive can continue to use a ` stringLiteral ` for the
435
+ quoted form (which is what they will do for relative references). But they can
436
+ also use a ` packagePath ` , which is a slash-separated series of segments, each of
437
+ which is a series of dot-separated components.*
438
+
439
+ ### Disallowing unquoted part and part-of directives.
378
440
379
- ### Part directive lookahead
441
+ We change the ` partDirective ` and ` partHeader ` rules to:
380
442
381
- * There are two directives for working with part files, ` part ` and ` part of ` .
382
- This means that when the parser sees ` part of ` , it doesn't immediately know if
383
- it is looking at a ` part ` directive followed by an unquoted identifier like
384
- ` part of; ` or ` part of.some/other.thing; ` versus a ` part of ` directive like
385
- ` part of thing; ` or ` part of 'uri.dart'; ` It must lookahead past the ` of `
386
- identifier to see if the next token is ` ; ` , ` . ` , ` / ` , or another identifier.*
443
+ ```
444
+ partDirective ::= metadata 'part' stringLiteral ';'
445
+ partHeader ::= metadata 'part' 'of' stringLiteral ';'
446
+ ```
447
+
448
+ * As part of [ augmentations] [ ] , we are also planning to [ expand the power of part
449
+ files] [ enhanced parts ] . That includes supporting configurable part directives
450
+ (but not configurable part-of. When/if that happens, this grammar will need to
451
+ be tweaked to something like:*
452
+
453
+ ```
454
+ partDirective ::= metadata 'part' configurableQuotedUri ';'
455
+ configurableQuotedUri ::= stringLiteral configurationQuotedUri*
456
+ configurationQuotedUri ::= 'if' '(' uriTest ')' stringLiteral
457
+ ```
387
458
388
- * This may add some complexity to parsing, but should be minor. Dart's grammar
389
- has other places that require much more (sometimes unbounded) lookahead. *
459
+ [ augmentations ] : https://github.com/dart-lang/language/blob/main/working/augmentation-libraries/feature-specification.md
460
+ [ enhanced parts ] : https://github.com/dart-lang/language/blob/main/working/augmentation-libraries/parts_with_imports.md
390
461
391
462
## Static semantics
392
463
@@ -461,8 +532,7 @@ There are no runtime semantics for this feature.
461
532
462
533
## Compatibility
463
534
464
- This feature is fully backwards compatible for ` import ` , ` export ` , and ` part `
465
- directives.
535
+ This feature is fully backwards compatible for ` import ` and ` export ` directives.
466
536
467
537
For all directives, we still allow quoted "dart:" and "package:" imports. Users
468
538
may be compelled to use the existing syntax in uncommon corner cases where the
@@ -474,73 +544,21 @@ migrated to the new style and the old quoted forms will be essentially vestigial
474
544
syntax (similar to names after ` library ` directives). A future version of Dart
475
545
may make a breaking change and remove support for the old syntax.
476
546
477
- ### Part-of directives
478
-
479
- The ` part of ` directive allows a library name after ` of ` instead of a string
480
- literal. With this proposal, that syntax is now ambiguous. Is it interpreted
481
- as a library name, or as an unquoted URI that should be converted to a URI?
482
- In other words, given:
483
-
484
- ``` dart
485
- part of foo.bar;
486
- ```
487
-
488
- Is the file saying it's a part of the library containing ` library foo.bar; ` or
489
- that it's part of the library found at URI ` package:foo.bar/bar.dart ` ?
490
-
491
- Library names in ` part of ` directives have been deprecated for many years
492
- because the syntax doesn't work well with many tools. How is a given tool
493
- supposed to know where to find the library that happens to contain a ` library `
494
- directive with that name? The quoted URI syntax was added later specifically to
495
- address that point and users are encouraged by documentation and lints to use
496
- the quoted syntax.
497
-
498
- Looking at a corpus of 122,420 files:
499
-
500
- ```
501
- -- Directive (443733 total) --
502
- 352744 ( 79.495%): import =========================================
503
- 55471 ( 12.501%): export =======
504
- 17823 ( 4.017%): part ===
505
- 17695 ( 3.988%): part of ===
506
- ```
507
-
508
- So ` part of ` directives are fairly rare to begin with. Of them, most use the
509
- recommended URI syntax and would not be affected by this change:
510
-
511
- ```
512
- -- Part of (17695 total) --
513
- 13229 ( 74.761%): uri ===================================
514
- 4466 ( 25.239%): library name ============
515
- ```
516
-
517
- In total, only about 1% of directives are ` part of ` with a library name:
518
-
519
- ```
520
- -- URI (443733 total) --
521
- 352744 ( 79.495%): import ===========================
522
- 55471 ( 12.501%): export =====
523
- 17823 ( 4.017%): part ==
524
- 13229 ( 2.981%): part of with uri =
525
- 4466 ( 1.006%): part of with library name =
526
- ```
527
-
528
- Given that, I propose that we make a ** breaking change** and remove support for
529
- the long-deprecated library name syntax from ` part of ` directives. An unquoted
530
- series of identifiers after ` part of ` then gets unambiguously interpreted as
531
- this proposal's semantics. In other words, ` part of foo.bar; ` is part of the
532
- library at ` package:foo/bar.dart ` , not part of the library with name ` foo.bar ` .
533
-
534
- Users affected by the breakage can and should update their ` part of ` directive
535
- to point to the URI of the library that the file is a part of, using either the
536
- quoted or unquoted syntax.
547
+ This proposal makes a ** breaking change** to disallow unquoted library names in
548
+ ` part of ` directives.
537
549
538
550
### Language versioning
539
551
540
552
To avoid breaking existing ` part of ` directives, this change is language
541
- versioned. Only libraries whose language version is at or above the version that
542
- this proposal ships in can use this new unquoted syntax in ` part of ` or any
543
- other directive.
553
+ versioned.
554
+
555
+ Only libraries whose language version is at or above the version that this
556
+ proposal ships in can use this new unquoted syntax in ` import ` and ` export `
557
+ directives.
558
+
559
+ In language versions before the version this feature ships in, code may
560
+ continue to use the old unquoted library name syntax in ` part of ` directives
561
+ but users are encouraged to migrate away from that syntax.
544
562
545
563
## Tooling
546
564
@@ -570,6 +588,10 @@ new unquoted style whenever an existing directive could use it.
570
588
571
589
## Changelog
572
590
591
+ ### 0.5
592
+
593
+ - Require ` part ` and ` part of ` directives to use quoted paths (#4038 ).
594
+
573
595
### 0.4
574
596
575
597
- Allow reserved words and built-in identifiers as path components (#3984 ).
0 commit comments