-
Notifications
You must be signed in to change notification settings - Fork 11
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
Generalizes to support multiple migrators #16
Conversation
There's now a `Migrator` class that additional migrators can extend. Most migrators will want to extend `MigratorBase`, which handles the tree traversal. For now, `MigratorBase` only operates on a single stylesheet, with the dependency migration implemented only by `ModuleMigrator`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you planning to have Migrator
stay non-recursive? If so, what's the plan for migrating entire projects at once?
--migrate-deps is now a global flag, so additional migrators should not need to re-implement dependency migration unless they need additional special logic like the module migrator needs. The generic migration classes are now split into Migrator and MigrationVisitor. Each Migrator is a Command and should contain state for the entire migration run. Most migrators will also want to create a private subclass of MigrationVisitor that they call from Migrator.migrateFile. A new instance of the MigrationVisitor will be created for each stylesheet being migrated, so it contains per-stylesheet state, similar to what StylesheetMigration used to be for the module migrator.
I've updated this to now have the generic migration support split into I've also made the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is shaping up really nicely! Thanks for bearing with my intense reviews 😅.
The migrator now uses URLs instead of paths, and loads files using the FilesystemImporter. `Migrator.migrated` has been removed in favor of having `Migrator.migrateFile` and `MigrationVisitor.run` return it.
lib/src/migration_visitor.dart
Outdated
visitStylesheet(stylesheet); | ||
var results = getMigratedContents(); | ||
if (results != null) { | ||
migrator.migrated[path] = results; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question. I'd say make the migrated
field private to MigrationVisitor
and give it total responsibility for handling the output, but you need to pass it through newInstance()
somehow...
What if we restructure this so that you don't need to construct multiple visitors at all? Rather than passing a URL to the constructor, pass it to run()
. That also means that when we get around to de-duplicating repeated imports/uses (which will probably be necessary for large-scale performance), there's a natural place for that as well.
This does mean that per-file state can't just be stored as final fields on the subclass. But you can override visitStylesheet()
to set it temporarily:
@override
void visitStylesheet(StylesheetNode node) {
var oldNamespaces = _namespaces;
var oldAdditionalUseRules = _additionalUseRules;
var oldConfigurableVariables = _configurableVariables;
_namespaces = {};
_additionalUseRules = Set();
_configurableVariables = normalizedSet();
super.visitStylesheet(node);
_namespaces = oldNamespaces;
_additionalUseRules = oldAdditionalUseRules;
_configurableVariables = oldConfigurableVariables;
}
This is basically how Dart Sass's EvaluateVisitor
works. WDYT?
Changed Previously, the module migrator needed to access the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to factor out the configurable-variables change into a separate PR? It's kind of tough to review this when it's changing multiple things at once.
A single MigrationVisitor is now reused instead of constructing a new instance for each dependency. This also removes support for configurable variables, since the previous implementation of this was both hard to implement with a single MigrationVisitor and incorrect when the configurable variables were declared in an indirect dependency. A subsequent PR will add this back with a new implementation that fixes the bug with indirect dependencies.
The old behavior would be hard to implement with a single MigrationVisitor, so I removed support for configurable variables entirely and will add them back with the new implementation in a separate PR. |
lib/src/migrators/module.dart
Outdated
final _globalFunctions = normalizedMap<FunctionRule>(); | ||
|
||
/// Namespaces of modules used in this stylesheet. | ||
Map<Uri, String> _namespaces = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can leave off the initializer here; this value will never be used, since it's always going to be set in visitStylesheet()
.
lib/src/migrators/module.dart
Outdated
if (results == null) return null; | ||
var semicolon = _currentUrl.path.endsWith('.sass') ? "" : ";"; | ||
var uses = _additionalUseRules.map((use) => '@use "$use"$semicolon\n'); | ||
return uses.join("") + results; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return uses.join("") + results; | |
return uses.join() + results; |
lib/src/migrators/module.dart
Outdated
_localScope = _localScope.parent; | ||
} | ||
|
||
/// Adds a namespace to any function call that require it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Adds a namespace to any function call that require it. | |
/// Adds a namespace to any function call that requires it. |
Resolves #19.
There's now a
Migrator
class that additional migrators can extend.Most migrators will want to extend
MigratorBase
, which handles the tree traversal. For now,MigratorBase
only operates on a single stylesheet, with the dependency migration implemented only byModuleMigrator
.