@@ -25,6 +25,7 @@ import 'module/reference_source.dart';
25
25
import 'module/references.dart' ;
26
26
import 'module/unreferencable_members.dart' ;
27
27
import 'module/unreferencable_type.dart' ;
28
+ import 'module/use_allowed.dart' ;
28
29
29
30
/// Migrates stylesheets to the new module system.
30
31
class ModuleMigrator extends Migrator {
@@ -99,17 +100,19 @@ class ModuleMigrator extends Migrator {
99
100
'You must provide --remove-prefix with --forward=prefixed so we know '
100
101
'which prefixed members to forward.' );
101
102
}
103
+ var safeAtRules = (argResults! ['safe-at-rule' ] as List <String >).toSet ();
102
104
103
- var references = References (importCache, stylesheet, importer,
104
- safeAtRules : argResults ! [ 'safe-at-rule' ] as List < String > );
105
+ var references =
106
+ References (importCache, stylesheet, importer, safeAtRules : safeAtRules );
105
107
var visitor = _ModuleMigrationVisitor (
106
108
importCache, references, globalResults! ['load-path' ] as List <String >,
107
109
migrateDependencies: migrateDependencies,
108
110
builtInOnly: builtInOnly,
109
111
prefixesToRemove: (argResults! ['remove-prefix' ] as List <String >)
110
112
.map ((prefix) => prefix.replaceAll ('_' , '-' )),
111
113
forwards: forwards,
112
- unsafeHoist: argResults! ['unsafe-hoist' ] as bool );
114
+ unsafeHoist: argResults! ['unsafe-hoist' ] as bool ,
115
+ safeAtRules: safeAtRules);
113
116
var migrated = visitor.run (stylesheet, importer);
114
117
_filesWithRenamedDeclarations.addAll (
115
118
{for (var member in visitor.renamedMembers.keys) member.sourceUrl});
@@ -188,8 +191,9 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
188
191
/// or `@forward` rule, or null if none has been visited yet.
189
192
FileLocation ? _afterLastImport;
190
193
191
- /// Whether @use and @forward are allowed in the current context.
192
- var _useAllowed = true ;
194
+ /// The state of whether `@use` and `@forward` are allowed at the current
195
+ /// point in the file.
196
+ var _useAllowed = UseAllowed .allowed;
193
197
194
198
/// Whether an import-only stylesheet should be generated.
195
199
///
@@ -231,6 +235,10 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
231
235
/// emit CSS.
232
236
final bool unsafeHoist;
233
237
238
+ /// CSS at rules that should be considered to not emit CSS for the purpose
239
+ /// of hoisting late `@import` rules.
240
+ final Set <String > safeAtRules;
241
+
234
242
/// Constructs a new module migration visitor.
235
243
///
236
244
/// [importCache] must be the same one used by [references] .
@@ -248,7 +256,8 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
248
256
required this .builtInOnly,
249
257
required this .unsafeHoist,
250
258
Iterable <String > prefixesToRemove = const [],
251
- this .forwards = const {}})
259
+ this .forwards = const {},
260
+ this .safeAtRules = const {}})
252
261
: loadPaths = List .unmodifiable (
253
262
loadPaths.map ((path) => p.toUri (p.absolute (path)).path)),
254
263
prefixesToRemove = UnmodifiableSetView (prefixesToRemove.toSet ());
@@ -470,7 +479,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
470
479
__additionalRelativeUseRules = {};
471
480
_beforeFirstImport = null ;
472
481
_afterLastImport = null ;
473
- _useAllowed = true ;
482
+ _useAllowed = UseAllowed .allowed ;
474
483
super .visitStylesheet (node);
475
484
__namespaces = oldNamespaces;
476
485
__forwardedUrls = oldForwardedUrls;
@@ -804,7 +813,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
804
813
/// Visits a `@function` rule, renaming if necessary.
805
814
@override
806
815
void visitFunctionRule (FunctionRule node) {
807
- _useAllowed = false ;
816
+ _useAllowed = UseAllowed .notAllowed ;
808
817
_renameReference (nameSpan (node), MemberDeclaration (node));
809
818
super .visitFunctionRule (node);
810
819
}
@@ -816,7 +825,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
816
825
var (staticImports, dynamicImports) =
817
826
partitionOnType <Import , StaticImport , DynamicImport >(node.imports);
818
827
if (dynamicImports.isEmpty) {
819
- _useAllowed = false ;
828
+ _useAllowed = _useAllowed. lowerToRequiresHoist () ;
820
829
return ;
821
830
}
822
831
String rulesText;
@@ -853,10 +862,11 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
853
862
visitDependency (ruleUrl, import.span);
854
863
_upstreamStylesheets.remove (currentUrl);
855
864
}
856
- } else if (_useAllowed) {
865
+ } else if (_useAllowed.canMigrateInPlace ) {
857
866
inPlaceUseRules.addAll (_migrateImportToRules (ruleUrl, import.span));
858
867
} else if (! isNested &&
859
- (! (references.fileEmitsCss[canonicalUrl] ?? true ) ||
868
+ (_useAllowed.canAlwaysSafelyHoist ||
869
+ ! (references.fileEmitsCss[canonicalUrl] ?? true ) ||
860
870
(unsafeHoist &&
861
871
references.anyMemberReferenced (
862
872
canonicalUrl, currentUrl)))) {
@@ -878,14 +888,14 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
878
888
} else {
879
889
addPatch (Patch (node.span, rulesText));
880
890
}
881
- if (_useAllowed) {
891
+ if (_useAllowed.canMigrateInPlace ) {
882
892
_beforeFirstImport ?? = node.span.start;
883
893
_afterLastImport = afterImport (node,
884
894
shouldHaveSemicolon: ! currentUrl.path.endsWith ('.sass' ));
885
895
}
886
896
887
897
if (staticImports.isNotEmpty) {
888
- _useAllowed = false ;
898
+ _useAllowed = _useAllowed. lowerToRequiresHoist () ;
889
899
addPatch (Patch .insert (
890
900
_afterLastImport ?? node.span.file.location (0 ),
891
901
'$indent @import ' +
@@ -906,7 +916,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
906
916
/// redirect to a different path to be migrated in-place.
907
917
List <String > _migrateImportToRules (Uri ruleUrl, FileSpan context) {
908
918
var (canonicalUrl, config, forwardForConfig) =
909
- _migrateImportCommon (ruleUrl, context);
919
+ _migrateImportCommon (ruleUrl, context, toLoadCss : false );
910
920
911
921
var asClause = '' ;
912
922
var defaultNamespace = namespaceForPath (ruleUrl.path);
@@ -955,7 +965,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
955
965
}
956
966
957
967
var (canonicalUrl, config, forwardForConfig) =
958
- _migrateImportCommon (ruleUrl, context);
968
+ _migrateImportCommon (ruleUrl, context, toLoadCss : true );
959
969
if (forwardForConfig != null ) {
960
970
throw MigrationSourceSpanException (
961
971
"This declaration attempts to override a default value in an "
@@ -990,7 +1000,12 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
990
1000
/// `meta.load-css` . The third is a string of variables that should be added
991
1001
/// to a `show` clause of a `@forward` rule so that they can be configured by
992
1002
/// an upstream file.
993
- (Uri , String ? , String ? ) _migrateImportCommon (Uri ruleUrl, FileSpan context) {
1003
+ ///
1004
+ /// When [toLoadCss] is false, this uses the variable syntax for configuration
1005
+ /// used by `@use` . When it is true, it instead uses the map syntax used by
1006
+ /// `meta.load-css()` .
1007
+ (Uri , String ? , String ? ) _migrateImportCommon (Uri ruleUrl, FileSpan context,
1008
+ {required bool toLoadCss}) {
994
1009
var oldConfiguredVariables = __configuredVariables;
995
1010
__configuredVariables = {};
996
1011
_upstreamStylesheets.add (currentUrl);
@@ -1057,7 +1072,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
1057
1072
var end = start + semicolon.length;
1058
1073
if (span.file.span (end, end + 1 ).text == '\n ' ) end++ ;
1059
1074
addPatch (patchDelete (span.file.span (start, end)));
1060
- var nameFormat = _useAllowed ? '\$ $ name ' : '"$ name " ' ;
1075
+ var nameFormat = toLoadCss ? '"$ name " ' : '\$ $ name ' ;
1061
1076
configured.add ("$nameFormat : ${variable .member .expression }" );
1062
1077
}
1063
1078
});
@@ -1157,7 +1172,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
1157
1172
/// Adds a namespace to any mixin include that requires it.
1158
1173
@override
1159
1174
void visitIncludeRule (IncludeRule node) {
1160
- _useAllowed = false ;
1175
+ _useAllowed = UseAllowed .notAllowed ;
1161
1176
super .visitIncludeRule (node);
1162
1177
if (node.namespace != null ) return ;
1163
1178
if (builtInOnly && references.sources[node] is ! BuiltInSource ) return ;
@@ -1178,7 +1193,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
1178
1193
/// Visits a `@mixin` rule, renaming it if necessary.
1179
1194
@override
1180
1195
void visitMixinRule (MixinRule node) {
1181
- _useAllowed = false ;
1196
+ _useAllowed = UseAllowed .notAllowed ;
1182
1197
if (! builtInOnly) _renameReference (nameSpan (node), MemberDeclaration (node));
1183
1198
super .visitMixinRule (node);
1184
1199
}
@@ -1421,84 +1436,88 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
1421
1436
/// Disallows `@use` after `@at-root` rules.
1422
1437
@override
1423
1438
void visitAtRootRule (AtRootRule node) {
1424
- _useAllowed = false ;
1439
+ _useAllowed = UseAllowed .notAllowed ;
1425
1440
super .visitAtRootRule (node);
1426
1441
}
1427
1442
1428
- /// Disallows `@use` after at-rules.
1443
+ /// Disallows `@use` after at-rules depending on [safeAtRules] .
1429
1444
@override
1430
1445
void visitAtRule (AtRule node) {
1431
- _useAllowed = false ;
1446
+ var oldUseAllowed = _useAllowed;
1447
+ _useAllowed = UseAllowed .notAllowed;
1432
1448
super .visitAtRule (node);
1449
+ if (safeAtRules.contains (node.name.asPlain)) {
1450
+ _useAllowed = oldUseAllowed.lowerToRequiresHoist ();
1451
+ }
1433
1452
}
1434
1453
1435
- /// Disallows `@use` after `@debug` rules.
1454
+ /// Requires hoisting `@use` after `@debug` rules.
1436
1455
@override
1437
1456
void visitDebugRule (DebugRule node) {
1438
- _useAllowed = false ;
1457
+ _useAllowed = _useAllowed. lowerToRequiresHoist () ;
1439
1458
super .visitDebugRule (node);
1440
1459
}
1441
1460
1442
1461
/// Disallows `@use` after `@each` rules.
1443
1462
@override
1444
1463
void visitEachRule (EachRule node) {
1445
- _useAllowed = false ;
1464
+ _useAllowed = UseAllowed .notAllowed ;
1446
1465
super .visitEachRule (node);
1447
1466
}
1448
1467
1449
1468
/// Disallows `@use` after `@error` rules.
1450
1469
@override
1451
1470
void visitErrorRule (ErrorRule node) {
1452
- _useAllowed = false ;
1471
+ _useAllowed = UseAllowed .notAllowed ;
1453
1472
super .visitErrorRule (node);
1454
1473
}
1455
1474
1456
1475
/// Disallows `@use` after `@for` rules.
1457
1476
@override
1458
1477
void visitForRule (ForRule node) {
1459
- _useAllowed = false ;
1478
+ _useAllowed = UseAllowed .notAllowed ;
1460
1479
super .visitForRule (node);
1461
1480
}
1462
1481
1463
1482
/// Disallows `@use` after `@if` rules.
1464
1483
@override
1465
1484
void visitIfRule (IfRule node) {
1466
- _useAllowed = false ;
1485
+ _useAllowed = UseAllowed .notAllowed ;
1467
1486
super .visitIfRule (node);
1468
1487
}
1469
1488
1470
1489
/// Disallows `@use` after `@media` rules.
1471
1490
@override
1472
1491
void visitMediaRule (MediaRule node) {
1473
- _useAllowed = false ;
1492
+ _useAllowed = UseAllowed .notAllowed ;
1474
1493
super .visitMediaRule (node);
1475
1494
}
1476
1495
1477
1496
/// Disallows `@use` after style rules.
1478
1497
@override
1479
1498
void visitStyleRule (StyleRule node) {
1480
- _useAllowed = false ;
1499
+ _useAllowed = UseAllowed .notAllowed ;
1481
1500
super .visitStyleRule (node);
1482
1501
}
1483
1502
1484
1503
/// Disallows `@use` after `@supports` rules.
1485
1504
@override
1486
1505
void visitSupportsRule (SupportsRule node) {
1487
- _useAllowed = false ;
1506
+ _useAllowed = UseAllowed .notAllowed ;
1488
1507
super .visitSupportsRule (node);
1489
1508
}
1490
1509
1491
- /// Disallows `@use` after `@warn` rules.
1510
+ /// Requires hoisting `@use` after `@warn` rules.
1492
1511
@override
1493
1512
void visitWarnRule (WarnRule node) {
1494
- _useAllowed = false ;
1513
+ _useAllowed = _useAllowed. lowerToRequiresHoist () ;
1495
1514
super .visitWarnRule (node);
1496
1515
}
1497
1516
1498
1517
/// Disallows `@use` after `@while` rules.
1499
1518
@override
1500
1519
void visitWhileRule (WhileRule node) {
1501
- _useAllowed = false ;
1520
+ _useAllowed = UseAllowed .notAllowed ;
1502
1521
super .visitWhileRule (node);
1503
1522
}
1504
1523
}
0 commit comments