Open juliocbcotta opened 5 years ago
The solution usually suggested is to not use parts. Instead use a separate library with its own imports.
The only reason to use a part file, instead of just a library, is to allow access to private members of other parts of the same library. If you need that, and need extra imports, then there is currently no solution. This can happen for generated code (a serializer might need access to private fields, and might need access to dart:convert
for JSON encoding).
Adding imports to parts would definitely make the imports only be visible inside that part. This is a new kind of scope (the declaration scope of the part can see the import scope of itself, and of its parent library, and the declaration scope of the parent library, and it adds its declarations to the parent library's declaration scope, but not its imports. Not even prefixed imports. Will imports shadow the main library declarations? Probably not. So, we'll have a lexical scope structure that is (main-imports, part-imports, declarations) in the part and (main-imports, declarations) in the main library, which means that the declarations do not have a single fixed parent scope any more).
The alternative approach to solving this problem would be to allow some libraries to access private members of other libraries, sharing private namespace between two or more "friend" libraries. The difference would be that you could import the other libraries directly, not just as parts of the "main" library, otherwise it would be equivalent to part files with imports.
Sharing private namespace is not a feature we'd allow one library to opt-in to without the consent of the other libraries. We have privacy for a reason, and allowing anyone to override it just because it might be convenient, is a very big foot-gun. So, we'll want every library to mention the other libraries as friends. Then we are pretty much back to the part
/part of
relations, only without a single most-important library. The "friend" relations declarations would have to be a complete bi-directional graph for the involved libraries (all the libraries in a group must friend all the other libraries in the group, otherwise it's a compile-time error).
So, I think imports in part files is probably a better solution than friend libraries.
are there any plans on implementing this? issue is in open state for quite a bit of time now :(
Is there a proposal for the "friend" libraries ?
I sometimes encounter the following (but it might very well be a design mistake):
class A {
int _a;
}
class B {
int _b;
}
class C {
// need to access B._b, and A._a; C being in the same package, but I only want C to be able to access those properties.
}
I could make C the upper part file but that wouldn't fit how I do things (again could be an misdesign on my part). So I wouldn't want this feature if that would encourage misdesign.
A more practical example would be
class TimeRange {
Time _start;
Time _end;
}
class DateRange {
Date _start;
Date _end;
}
class Schedule {
DateTime get checkIn => // can't access needed properties :(
DateTime get checkOut => // can't do.
DateRange _selectedDateRange;
TimeRange _selectedTimeRange;
}
I usually use some mapper
methods for those cases but it's ugly and only intended for the "friend".
There's a proposal for this at https://github.com/dart-lang/language/blob/main/working/augmentation-libraries/parts_with_imports.md
Currently, when generating code, the
part
file can't have specific imports and they need to be added in the hand written file.This behavior restricts the ergonomics of code generation in: 1) Clients of code generating libraries need to update their hand written files with imports. 2) The hand written files have references to imports that are not used in that file.
Use case: A library split in two artifacts.
dependencies
dev_dependencies
The code generating library that need to check the
Platform
, something likePlatform.isAndroid
in the generated code.This means : The library client developer will need to add
import 'dart:io';
to the hand written code to make the project compile as this is the import that contains thePlatform
class.As I understand this need to declare by the imports "by hand" is meant to avoid a missing dependency in the project, but this could be avoid if the annotation library declares if it declares the package dependency.
The concrete example of the problem can be found here.