Skip to content

Commit 7fe3ce1

Browse files
authored
Use the new AST interfaces (#210)
This updates the migrator to be compatible with the recent changes to `DynamicImport.url` and `FunctionExpression.name`, and also uses the new `SassReference` and `SassDeclaration` interfaces. For now, it's still importing the Sass AST from `dart-sass`'s `src`, rather than from the new `sass_api`.
1 parent fdd698f commit 7fe3ce1

12 files changed

+84
-136
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.5.2
2+
3+
* No user-visible changes.
4+
15
## 1.5.1
26

37
### Division Migrator

lib/src/exception.dart

+6-3
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ class MigrationException implements Exception {
1717
String toString() => "Error: $message";
1818
}
1919

20+
// TODO(jathak): Stop extending [SassException] here.
21+
// ignore_for_file: subtype_of_sealed_class
22+
2023
/// A [MigrationException] that has source span information associated with it.
21-
//
22-
// This extends [SassException] to ensure that migrator exceptions are formatted
23-
// the same way as the syntax errors Sass throws.
24+
///
25+
/// This extends [SassException] to ensure that migrator exceptions are
26+
/// formatted the same way as the syntax errors Sass throws.
2427
class MigrationSourceSpanException extends SassException
2528
implements MigrationException {
2629
MigrationSourceSpanException(String message, FileSpan span)

lib/src/migration_visitor.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ abstract class MigrationVisitor extends RecursiveAstVisitor {
170170
if (migrateDependencies) {
171171
for (var import in node.imports) {
172172
if (import is DynamicImport) {
173-
visitDependency(Uri.parse(import.url), import.span, forImport: true);
173+
visitDependency(import.url, import.span, forImport: true);
174174
}
175175
}
176176
}

lib/src/migrators/division.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ class _DivisionMigrationVisitor extends MigrationVisitor {
163163
/// for new-syntax color functions.
164164
@override
165165
void visitFunctionExpression(FunctionExpression node) {
166-
visitInterpolation(node.name);
167166
if (_tryColorFunction(node)) return;
168167
visitArgumentInvocation(node.arguments);
169168
}
@@ -226,7 +225,7 @@ class _DivisionMigrationVisitor extends MigrationVisitor {
226225
/// Migrates [node] and returns true if it is a new-syntax color function or
227226
/// returns false if it is any other function.
228227
bool _tryColorFunction(FunctionExpression node) {
229-
if (!["rgb", "rgba", "hsl", "hsla"].contains(node.name.asPlain)) {
228+
if (!["rgb", "rgba", "hsl", "hsla"].contains(node.name)) {
230229
return false;
231230
}
232231

lib/src/migrators/module.dart

+22-21
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
124124

125125
/// Maps canonical URLs to the original URL and importer from the `@import`
126126
/// rule that last imported that URL.
127-
final _originalImports = <Uri, Tuple2<String, Importer>>{};
127+
final _originalImports = <Uri, Tuple2<Uri, Importer>>{};
128128

129129
/// Tracks members that are unreferencable in the current scope.
130130
var _unreferencable = UnreferencableMembers();
@@ -527,7 +527,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
527527
// namespace.
528528
var paths = {
529529
for (var source in sources)
530-
source: ruleUrlsForSources[source]!.split('/')
530+
source: ruleUrlsForSources[source]!.pathSegments.toList()
531531
..removeLast()
532532
..removeWhere((segment) => segment.contains('.'))
533533
};
@@ -586,10 +586,10 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
586586
/// Given a set of import sources, groups them by the number of path segments
587587
/// and sorts those groups from fewer to more segments.
588588
List<Set<ImportSource>> _orderSources(
589-
Map<ImportSource, String> ruleUrlsForSources) {
589+
Map<ImportSource, Uri> ruleUrlsForSources) {
590590
var byPathLength = <int, Set<ImportSource>>{};
591591
for (var entry in ruleUrlsForSources.entries) {
592-
var pathSegments = Uri.parse(entry.value).pathSegments;
592+
var pathSegments = entry.value.pathSegments;
593593
byPathLength.putIfAbsent(pathSegments.length, () => {}).add(entry.key);
594594
}
595595
return [
@@ -616,16 +616,17 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
616616
}
617617
if (references.sources.containsKey(node)) {
618618
var declaration = references.functions[node];
619+
var fnNameSpan = nameSpan(node);
619620
if (declaration != null) {
620621
_unreferencable.check(declaration, node);
621-
_renameReference(nameSpan(node), declaration);
622+
_renameReference(fnNameSpan, declaration);
622623
}
623624
_patchNamespaceForFunction(node, declaration, (namespace) {
624-
addPatch(patchBefore(node.name, '$namespace.'));
625+
addPatch(Patch.insert(fnNameSpan.start, '$namespace.'));
625626
});
626627
}
627628

628-
if (node.name.asPlain == "get-function") {
629+
if (node.name == "get-function") {
629630
var declaration = references.getFunctionReferences[node];
630631
if (declaration != null) {
631632
_unreferencable.check(declaration, node);
@@ -774,8 +775,8 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
774775
var indent = ' ' * node.span.start.column;
775776

776777
for (var import in dynamicImports) {
777-
String? ruleUrl = import.url;
778-
var tuple = importCache.canonicalize(Uri.parse(ruleUrl),
778+
Uri? ruleUrl = import.url;
779+
var tuple = importCache.canonicalize(ruleUrl,
779780
baseImporter: importer, baseUrl: currentUrl, forImport: true);
780781
var canonicalImport = tuple?.item2;
781782
if (canonicalImport != null &&
@@ -834,14 +835,14 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
834835
/// `@forward` rule from an import-only file that does not forward its
835836
/// corresponding regular file. This allows imports of import-only files that
836837
/// redirect to a different path to be migrated in-place.
837-
List<String> _migrateImportToRules(String ruleUrl, FileSpan context) {
838+
List<String> _migrateImportToRules(Uri ruleUrl, FileSpan context) {
838839
var tuple = _migrateImportCommon(ruleUrl, context);
839840
var canonicalUrl = tuple.item1;
840841
var config = tuple.item2;
841842
var forwardForConfig = tuple.item3;
842843

843844
var asClause = '';
844-
var defaultNamespace = namespaceForPath(ruleUrl);
845+
var defaultNamespace = namespaceForPath(ruleUrl.path);
845846
// If a member from this dependency is actually referenced, it should
846847
// already have a namespace from [_determineNamespaces], so we just use
847848
// a simple number suffix to resolve conflicts at this point.
@@ -877,7 +878,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
877878
///
878879
/// This is used for migrating `@import` rules that are nested or appear after
879880
/// some other rules.
880-
String _migrateImportToLoadCss(String ruleUrl, FileSpan context) {
881+
String _migrateImportToLoadCss(Uri ruleUrl, FileSpan context) {
881882
var oldUnreferencable = _unreferencable;
882883
_unreferencable = UnreferencableMembers(_unreferencable);
883884
for (var declaration in references.allDeclarations) {
@@ -919,20 +920,19 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
919920
/// to a `show` clause of a `@forward` rule so that they can be configured by
920921
/// an upstream file.
921922
Tuple3<Uri, String?, String?> _migrateImportCommon(
922-
String ruleUrl, FileSpan context) {
923+
Uri ruleUrl, FileSpan context) {
923924
var oldConfiguredVariables = __configuredVariables;
924925
__configuredVariables = {};
925926
_upstreamStylesheets.add(currentUrl);
926-
var parsedUrl = Uri.parse(ruleUrl);
927-
if (migrateDependencies) visitDependency(parsedUrl, context);
927+
if (migrateDependencies) visitDependency(ruleUrl, context);
928928
_upstreamStylesheets.remove(currentUrl);
929929

930-
var tuple = importCache.canonicalize(parsedUrl,
930+
var tuple = importCache.canonicalize(ruleUrl,
931931
baseImporter: importer, baseUrl: currentUrl);
932932

933933
if (tuple == null) {
934934
throw MigrationSourceSpanException(
935-
"Could not find Sass file at '${p.prettyUri(parsedUrl)}'.", context);
935+
"Could not find Sass file at '${p.prettyUri(ruleUrl)}'.", context);
936936
}
937937

938938
// Associate the importer for this URL with the resolved URL so that we can
@@ -1257,7 +1257,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
12571257
if (!_usedUrls.contains(url)) {
12581258
// Add new `@use` rule for indirect dependency
12591259
var tuple = _absoluteUrlToDependency(url);
1260-
var defaultNamespace = namespaceForPath(tuple.item1);
1260+
var defaultNamespace = namespaceForPath(tuple.item1.path);
12611261
// There are a few edge cases where the reference in [declaration] wasn't
12621262
// tracked by [references.sources], so we add a namespace with simple
12631263
// conflict resolution if one for this URL doesn't already exist.
@@ -1279,7 +1279,7 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
12791279
/// The first item of the returned tuple is the dependency, the second item
12801280
/// is true when this dependency is resolved relative to the current URL and
12811281
/// false when it's resolved relative to a load path.
1282-
Tuple2<String, bool> _absoluteUrlToDependency(Uri url, {Uri? relativeTo}) {
1282+
Tuple2<Uri, bool> _absoluteUrlToDependency(Uri url, {Uri? relativeTo}) {
12831283
relativeTo ??= currentUrl;
12841284
var tuple = _originalImports[url];
12851285
if (tuple != null && tuple.item2 is NodeModulesImporter) {
@@ -1305,9 +1305,10 @@ class _ModuleMigrationVisitor extends MigrationVisitor {
13051305
];
13061306
var relativePath = minBy<String, int>(potentialUrls, (url) => url.length)!;
13071307
var isRelative = relativePath == potentialUrls.first;
1308-
13091308
return Tuple2(
1310-
p.url.relative(p.url.join(p.url.dirname(relativePath), basename)),
1309+
Uri(
1310+
path: p.url
1311+
.relative(p.url.join(p.url.dirname(relativePath), basename))),
13111312
isRelative);
13121313
}
13131314

lib/src/migrators/module/member_declaration.dart

+3-20
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ import 'package:path/path.dart' as p;
1414
import '../../utils.dart';
1515

1616
/// A wrapper class for nodes that declare a variable, function, or mixin.
17-
///
18-
/// The member this class wraps will always be a [VariableDeclaration],
19-
/// an [Argument], a [MixinRule], or a [FunctionRule].
20-
class MemberDeclaration<T extends SassNode> {
17+
class MemberDeclaration<T extends SassDeclaration> {
2118
/// The original definition of the member, after all `@forward` rules have
2219
/// been resolved.
2320
final T member;
@@ -46,28 +43,14 @@ class MemberDeclaration<T extends SassNode> {
4643

4744
/// Creates a MemberDefinition for a [member] that was loaded from the same
4845
/// module it was defined.
49-
///
50-
/// The [member] must be a [VariableDeclaration], [Argument], [MixinRule], or
51-
/// [FunctionRule].
5246
MemberDeclaration(T member)
53-
: this._(member, () {
54-
if (member is VariableDeclaration) return member.name;
55-
if (member is Argument) return member.name;
56-
if (member is MixinRule) return member.name;
57-
if (member is FunctionRule) return member.name;
58-
throw ArgumentError(
59-
"MemberDefinition must contain a VariableDeclaration, Argument, "
60-
"MixinRule, or FunctionRule");
61-
}(), member.span.sourceUrl!);
47+
: this._(member, member.name, member.span.sourceUrl!);
6248

6349
/// Creates a MemberDefinition for a member that was forwarded through at
6450
/// least one non-import-only module.
6551
///
6652
/// The [forwarded] member is the member loaded by [forward].
6753
///
68-
/// The [member] must be a [VariableDeclaration], [Argument], [MixinRule], or
69-
/// [FunctionRule].
70-
///
7154
/// If [forward] comes from an import-only file, this returns an
7255
/// [ImportOnlyMemberDeclaration].
7356
factory MemberDeclaration.forward(
@@ -104,7 +87,7 @@ class MemberDeclaration<T extends SassNode> {
10487
}
10588

10689
/// A declaration for a member forwarded through an import-only file.
107-
class ImportOnlyMemberDeclaration<T extends SassNode>
90+
class ImportOnlyMemberDeclaration<T extends SassDeclaration>
10891
extends MemberDeclaration<T> {
10992
/// The prefix added to [name] by forwards through import-only files.
11093
final String importOnlyPrefix;

lib/src/migrators/module/reference_source.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ImportSource extends ReferenceSource {
3131

3232
/// The URL of the `@import` rule that loaded this member, or null if this
3333
/// is for an indirect dependency forwarded in an import-only file.
34-
final String? originalRuleUrl;
34+
final Uri? originalRuleUrl;
3535

3636
/// Creates an [ImportSource] for [url] from [import].
3737
///
@@ -158,7 +158,7 @@ class ImportOnlySource extends ReferenceSource {
158158
/// the URL of the `@import` rule that loaded that import-only file.
159159
///
160160
/// Otherwise, this will be null.
161-
final String? originalRuleUrl;
161+
final Uri? originalRuleUrl;
162162

163163
ImportOnlySource(this.url, this.realSourceUrl, this.originalRuleUrl);
164164

0 commit comments

Comments
 (0)