Augmentations: Allow parts in augmentations, augmentations in main library
The current augmentation feature specification introduces augmentation libraries which a main library or augmentation library can include. An augmentation library:
- Can contain augmentation declarations, and
- Cannot contain part files.
An augmentation library can contain multiple augmentations for the same declaration, and it can contain both a declaration and an augmentation for that declaration.
The main library file can contain part files, but cannot contain augmentations.
I suggest removing the restrictions from this:
- Allow augmentation libraries to have part files.
- Allow a non-augmentation library to contain augmentations.
The restrictions do not appear to be necessary, and I don't think we should be enforcing a purely stylistic choice on how people choose to organize their code. It's an unnecessary breach of orthogonality. (The one argument I can see is that allowing augmentations in part files will make the ordering of part files significant, where today it isn't. But today, no part file contains augmentations, so it won't be breaking. And if augmentation library order is significant, I have no problem with part file order being signficant if they include augmentations.)
The change would require only one new thing: Integrating part files in the augmentation application order.
My proposal is:
- Every (augmentation or non-augmentation) declaration in a library or augmentation library, including in its part files or transitive augmentation libraries, is ordered in augmentation application order.
- The ordering of the declarations for a library or augmentation library is:
- First the declarations in the main library file, in souce order.
- Then for each
partdeclaration of the library, in source order:- The declarations of that part file in source order.
- Then for each augmentation import of the library, in source order:
- All the declarations of that augmentation library in augmentation application order.
That is the same as the current specification if a main library contains no augmentations and an augmentation library contains no parts. Adding either will insert the augmentation library parts or main library augmentations in a consistent place.
The rule would still be that an augmentation of a declaration must occur after the declaration in augmentation application order, and that augmentations of the same declaration are applied in augmentation applicatation order, each's augmented references referring to the previous, possibly augmented, declaration.
(We could loosen that and allow non-augmentation declarations to be collected first, from the entire libray, and then augmentations are applied in order, so an augmentation can occur before the declaration it augments. It's probably not necessary, and it's easier to have only one order.)
Even if we won't allow augmentation libraries to have parts, or even part files to have augmentations, we should still allow main library files to contain agumentations. There is no reason not to, when the main library file can be just augment import "real_library.dart";. Basically, the main library should be able to be an augmentation library.
(If nothing else, that. Even if we choose to not allow it to also have parts.)
- Allow a non-augmentation library to contain augmentations.
I believe the main reason for not allowing this is to make it as non-breaking as possible, the new keywords augment and augmented are only valid within the scope of an augmentation and not a regular library.
For augmented, I am not concerned (it is already a contextual keyword only similar to await). For augment though, can we add that as a keyword and still allow members called augment? If so, then I probably would be fine with allowing augmentations in any library.
- Allow augmentation libraries to have part files.
I believe the main reason for not supporting mixing augmentations and part files is that it would make it easier to remove part files in the future, if we decided we wanted to do that.
It is a bit weird to have both long term.
For augment though, can we add that as a keyword and still allow members called augment?
We can make it a built-in in identifier, which the feature spec already does.
That allows the identifier to be used as a name anywhere except as a type name, type variable name and import prefix name.
It should (knock wood) be sufficient to ensure that any top level syntax starting with the identifier augment is not using it as a type, which is the only way an identifier can start a declaration. That's what we've been relying on until now, with all the other built-in identifiers.
That's also why it's often better to put it first in new syntax, than later, fx after import. (Import is special enough in it's syntax that is hard to cause ambiguity, but with import shorthands that might change.
A leading augment can then always be interpreted as prefixing another declaration. (Which can then also be allowed to start with a built-in in identifier.)
I think this is obsoleted by #3848