@@ -4,7 +4,7 @@ Author: Bob Nystrom
44
55Status: Accepted
66
7- Version 0.4 (see [ CHANGELOG] ( #CHANGELOG ) at end)
7+ Version 0.5 (see [ CHANGELOG] ( #CHANGELOG ) at end)
88
99Experiment flag: unquoted-imports
1010
@@ -341,20 +341,80 @@ after the directives outside of the path. These are all valid:
341341
342342``` dart
343343import /* 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?
346346 ;
347347```
348348
349349The syntax that results from the above few sections is simple to tokenize and
350350parse while looking like a single opaque "unquoted string" to users and tools.
351351
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+
352412## Syntax
353413
354414The normative stuff starts now. Here is the proposal:
355415
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 :
358418
359419```
360420uri ::= stringLiteral | packagePath
@@ -371,22 +431,33 @@ between any of the `segmentComponent`, `/`, or `.` tokens in a `packagePath`.
371431* In other words, there can be nothing except the terminals themselves from the
372432first ` segmentComponent ` in the ` packagePath ` to the last.*
373433
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.
378440
379- ### Part directive lookahead
441+ We change the ` partDirective ` and ` partHeader ` rules to:
380442
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+ ```
387458
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
390461
391462## Static semantics
392463
@@ -461,8 +532,7 @@ There are no runtime semantics for this feature.
461532
462533## Compatibility
463534
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.
466536
467537For all directives, we still allow quoted "dart:" and "package:" imports. Users
468538may 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
474544syntax (similar to names after ` library ` directives). A future version of Dart
475545may make a breaking change and remove support for the old syntax.
476546
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.
537549
538550### Language versioning
539551
540552To 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.
544562
545563## Tooling
546564
@@ -570,6 +588,10 @@ new unquoted style whenever an existing directive could use it.
570588
571589## Changelog
572590
591+ ### 0.5
592+
593+ - Require ` part ` and ` part of ` directives to use quoted paths (#4038 ).
594+
573595### 0.4
574596
575597- Allow reserved words and built-in identifiers as path components (#3984 ).
0 commit comments