Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

URI shorthands, not for parts #4038

Open
lrhn opened this issue Aug 15, 2024 · 0 comments
Open

URI shorthands, not for parts #4038

lrhn opened this issue Aug 15, 2024 · 0 comments
Labels
feature Proposed language feature that solves one or more problems import-shorthand unquoted-uris The unquoted URI feature

Comments

@lrhn
Copy link
Member

lrhn commented Aug 15, 2024

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 a part 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 invalid pkg.foo) would not become valid syntax for using package: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.

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

@lrhn lrhn added feature Proposed language feature that solves one or more problems import-shorthand labels Aug 15, 2024
@kallentu kallentu added the unquoted-uris The unquoted URI feature label Sep 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems import-shorthand unquoted-uris The unquoted URI feature
Projects
None yet
Development

No branches or pull requests

2 participants