Description
TL;DR: Don't allow part
and part of
to use shorthand URIs. They should always be relative URI references anyway. Added benefit is discontinuing the old syntax without immediately allowing the same syntax with a new meaning, making migration easier.
The URI shorthand spec allows the shorthand to be used for import
, export
, part
and part of
directives.
An unquoted URI shorthand can be used as shorthand for a dart:
or package:
URI. It cannot represent relative URI references.
The spec mentions parsing of part of
being tricky.
It removes support for part of library.name;
that refers to the name of a library introduced by its library declaration, and instead interprets part of library.name;
as part of "package:library.name/name.dart";
.
It also needs look-ahead because part of ...
could mean part "package:of/of.dart" ...
, so parsing will have to disambiguate by looking at what follows.
If followed immediately by ;
it means part "package:of/of.dart";
.
If it's followed by one identifier/reserved word only, before a ;
, then that identifier is a shorthand URI package name for that parent file of a part of
directive.
If it's followed by an identifier/reserved word and then .
or /
, it's definitely a URI shorthand for the parent file.
If it's followed by a if (
then it's a part
directive.
This is a lot of complication for something that will likely never be used.
With "parts-with-imports" it's made explicit that a part must be in the same package as its parent file. (It's a requirement made by the language versioning feature, not a single language version, a language by itself doesn't care, and the requirement has always been assumed, but not explicitly stated.) Most likely, the part and parent files must both be inside or outside of lib/
too.
That means that a part
directive, and a part of
directive, always can and should use a relative URI reference, which means it won't be using a shorthand. (Not unless/until we introduce a relative shorthand like ./foo
, at which point I'd allow part
/part of
to use relative shorthands only.)
I'd still disallow part of library.name;
because it looks ambiguous, and because we'll be removing it in "parts with imports" anyway, so we might as well remove it here, if this feature launches first.
The benefit would be:
- Less parsing complexity. The
part of
is unambiguously starting apart of
directive. - An existing
part of pkg.foo;
would become invalid, not change meaning. That makes migration easier. - Writing
part of;
by accident (perhaps removing the now invalidpkg.foo
) would not become valid syntax for usingpackage:of/of.dart
as a part. (It probably won't succeed, causing some other downstream compilation error, so tools can still recognize and report it specially if they want to.) - Pushes people away from using
part foo;
,- which they might mistakenly assume means
part "foo.dart";
. - or if they do mean
package:foo/foo.dart
, force them to write that out, which would encourage using the relative URI.
- which they might mistakenly assume means
The drawback is lack of orthogonality. In some places where you can use a URI, you can use a shorthand.
In other places you cannot.
With "parts-with-imports" parts can have conditional URIs, removing an existing lack of orthogonality, so adding another one here feels counter-productive.
However, of import
, export
and part
, one is not like the other two. Both import
and export
refer to libraries, potentially from other packages (even likely, otherwise you can use a relative import anyway, and don't need the shorthand so much), where part
refers to files inside the current package. Shorthand URIs are for full package:
URIs, and part
/part of
never need those, and shouldn't use them. Not allowing you to do something that you shouldn't be doing anyway, isn't much of a loss. At best, nobody ever notices, because they didn't try. Or we catch someone writing something unquoted that they think is relative, when it really isn't.
We can explicitly use the narrative that unquoted URIs are for libraries, not for files. We give people a new syntax for referring to libraries in other packages. We don't give them a syntax to refer to files in other packages, because that's not something you can do. The syntax can be used for libraries in the current package, but also not for arbitrary files.
We can allow part of unquotedUri;
later if we want to.
Disallowing it now, at the point where we discontinue part of library.name;
, makes that a clean cut, and that alone should be reason enough to not give the same syntax new meaning immediately. At least wait until actively maintained code has changed all their part of
directives to URIs.
@dart-lang/language-team