Skip to content

Commit

Permalink
Add media query migrator (#228)
Browse files Browse the repository at this point in the history
This PR adds a new `handleDeprecation` method to `Migrator`, which the
new migrator uses instead of attempting to duplicate the logic from the
parser.
  • Loading branch information
jathak committed Sep 7, 2022
1 parent 874c62f commit 292c587
Show file tree
Hide file tree
Showing 15 changed files with 131 additions and 112 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 1.7.0

### Media Logic Migrator

* Adds a new migrator for migrating [deprecated `@media` query logic].

[deprecated `@media` query logic]: https://sass-lang.com/d/media-logic

## 1.6.0

### Strict Unary Migrator
Expand Down
27 changes: 26 additions & 1 deletion lib/src/migrator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:sass_api/sass_api.dart';
import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';

import 'exception.dart';
import 'io.dart';
Expand Down Expand Up @@ -57,6 +58,10 @@ abstract class Migrator extends Command<Map<Uri, String>> {
Map<Uri, String> migrateFile(
ImportCache importCache, Stylesheet stylesheet, Importer importer);

/// This is called whenever a deprecation warning is emitted during parsing.
@protected
void handleDeprecation(String message, FileSpan? span) {}

/// Runs this migrator.
///
/// Each entrypoint is migrated separately. If a stylesheet is migrated more
Expand All @@ -70,7 +75,8 @@ abstract class Migrator extends Command<Map<Uri, String>> {
var importer = FilesystemImporter('.');
var importCache = ImportCache(
importers: [NodeModulesImporter()],
loadPaths: globalResults!['load-path']);
loadPaths: globalResults!['load-path'],
logger: _DeprecationLogger(this));

var entrypoints = [
for (var argument in argResults!.rest)
Expand Down Expand Up @@ -126,3 +132,22 @@ abstract class Migrator extends Command<Map<Uri, String>> {
}
}
}

/// A silent logger that calls [Migrator.handleDeprecation] when it receives a
/// deprecation warning
class _DeprecationLogger implements Logger {
final Migrator migrator;

_DeprecationLogger(this.migrator);

@override
void debug(String message, SourceSpan span) {}

@override
void warn(String message,
{FileSpan? span, Trace? trace, bool deprecation = false}) {
if (deprecation) {
migrator.handleDeprecation(message, span);
}
}
}
57 changes: 57 additions & 0 deletions lib/src/migrators/media_logic.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2022 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'package:sass_api/sass_api.dart';
import 'package:source_span/source_span.dart';

import '../migration_visitor.dart';
import '../migrator.dart';
import '../patch.dart';

/// Migrates deprecated `@media` query syntax to use interpolation.
class MediaLogicMigrator extends Migrator {
final name = 'media-logic';
final description = r'Migrates deprecated `@media` query syntax.\n'
'See https://sass-lang.com/d/media-logic.';

/// For each stylesheet URL, the set of relevant spans that require migration.
final _expressionsToMigrate = <Uri, Set<FileSpan>>{};

@override
void handleDeprecation(String message, FileSpan? span) {
if (span == null) return;
if (!message.startsWith('Starting a @media query with ')) return;
_expressionsToMigrate.putIfAbsent(span.sourceUrl!, () => {}).add(span);
}

@override
Map<Uri, String> migrateFile(
ImportCache importCache, Stylesheet stylesheet, Importer importer) {
var visitor = _MediaLogicVisitor(
importCache, migrateDependencies, _expressionsToMigrate);
var result = visitor.run(stylesheet, importer);
missingDependencies.addAll(visitor.missingDependencies);
return result;
}
}

class _MediaLogicVisitor extends MigrationVisitor {
/// For each stylesheet URL, the set of relevant spans that require migration.
final Map<Uri, Set<FileSpan>> _expressionsToMigrate;

_MediaLogicVisitor(ImportCache importCache, bool migrateDependencies,
this._expressionsToMigrate)
: super(importCache, migrateDependencies);

@override
void beforePatch(Stylesheet node) {
var expressions = _expressionsToMigrate[node.span.sourceUrl] ?? {};
for (var expression in expressions) {
addPatch(Patch.insert(expression.start, '#{'));
addPatch(Patch.insert(expression.end, '}'));
}
}
}
2 changes: 2 additions & 0 deletions lib/src/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:term_glyph/term_glyph.dart' as glyph;

import 'io.dart';
import 'migrators/division.dart';
import 'migrators/media_logic.dart';
import 'migrators/module.dart';
import 'migrators/namespace.dart';
import 'migrators/strict_unary.dart';
Expand Down Expand Up @@ -54,6 +55,7 @@ class MigratorRunner extends CommandRunner<Map<Uri, String>> {
..addFlag('version',
help: 'Print the version of the Sass migrator.', negatable: false);
addCommand(DivisionMigrator());
addCommand(MediaLogicMigrator());
addCommand(ModuleMigrator());
addCommand(NamespaceMigrator());
addCommand(StrictUnaryMigrator());
Expand Down
5 changes: 3 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: sass_migrator
version: 1.6.0
version: 1.7.0
description: A tool for running migrations on Sass files
homepage: https://github.com/sass/migrator

Expand All @@ -17,8 +17,9 @@ dependencies:
node_interop: ^2.0.2
node_io: ^2.2.0
path: ^1.8.0
sass_api: ^3.0.0
sass_api: ^3.0.4
source_span: ^1.8.1
stack_trace: ^1.10.0
string_scanner: ^1.1.0
term_glyph: ^1.2.0
tuple: ^2.0.0
Expand Down
31 changes: 4 additions & 27 deletions test/migrators/README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,10 @@
# Migration Tests

Each migrator should have:
Each migrator should have a directory `<migrator-name>` that contains that
migrator's HRX tests.

* A `<migrator-name>_dart_test.dart` file that looks like:

```dart
import '../utils.dart';
main() {
testMigrator("<migrator-name>");
}
```

* A `<migrator-name>_node_test.dart` file that looks like:

```dart
@Tags("node")
import 'package:test/test.dart';
import '../utils.dart';
main() {
runNodeTests = true;
testMigrator("<migrator-name>");
}
```

* A directory `<migrator-name>` that contains that migrator's HRX tests,
A line `testMigrator(<migrator-name>)` should then be added to the `main`
function of `migrator_dart_test.dart`.

## HRX Format

Expand Down
11 changes: 0 additions & 11 deletions test/migrators/division_dart_test.dart

This file was deleted.

16 changes: 0 additions & 16 deletions test/migrators/division_node_test.dart

This file was deleted.

25 changes: 25 additions & 0 deletions test/migrators/media_logic/add_interpolation.hrx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<==> input/entrypoint.scss
@media (not (foo)) {
a {b: c}
}

@media ((foo) and (bar)) {
d {e: f}
}

@media ((foo) or (bar)) {
g {h: i}
}

<==> output/entrypoint.scss
@media (#{not (foo)}) {
a {b: c}
}

@media (#{(foo) and (bar)}) {
d {e: f}
}

@media (#{(foo) or (bar)}) {
g {h: i}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@
import '../utils.dart';

main() {
testMigrator("division");
testMigrator("media_logic");
testMigrator("module");
testMigrator("namespace");
testMigrator("strict_unary");
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

import 'package:test/test.dart';

import 'migrator_dart_test.dart' as dart;
import '../utils.dart';

main() {
runNodeTests = true;
testMigrator("strict_unary");
dart.main();
}
11 changes: 0 additions & 11 deletions test/migrators/module_dart_test.dart

This file was deleted.

16 changes: 0 additions & 16 deletions test/migrators/module_node_test.dart

This file was deleted.

11 changes: 0 additions & 11 deletions test/migrators/namespace_dart_test.dart

This file was deleted.

16 changes: 0 additions & 16 deletions test/migrators/namespace_node_test.dart

This file was deleted.

0 comments on commit 292c587

Please sign in to comment.