Skip to content

Commit

Permalink
Add --fatal-deprecations and --future-deprecations (#1820)
Browse files Browse the repository at this point in the history
* Add fatal/futureDeprecations to Dart API

This adds a new `Deprecation` class that specifies an ID for each
deprecated feature along with what Dart Sass version deprecated it.

The compile functions allow you to pass a set of `fatalDeprecations`
that will cause an error instead of a warning. You can also pass a set
of `futureDeprecations`, which let you opt-in to deprecations (like
`@import`) early.

* Add future deprecation for `@import`

* Add flags

* Merge colorUnits and randomWithUnits

* Update changelogs and pubspecs

* Add tests

* Use isFuture instead of deprecatedIn == null
* Split warnForDeprecation from warn

* Add missing word to error message
  • Loading branch information
jathak committed Mar 10, 2023
1 parent 9417b6e commit 8f8138d
Show file tree
Hide file tree
Showing 27 changed files with 731 additions and 173 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
## 1.59.0

### Command Line Interface

* Added a new `--fatal-deprecation` flag that lets you treat a deprecation
warning as an error. You can pass an individual deprecation ID
(e.g. `slash-div`) or you can pass a Dart Sass version to treat all
deprecations initially emitted in that version or earlier as errors.

* New `--future-deprecation` flag that lets you opt into warning for use of
certain features that will be deprecated in the future. At the moment, the
only option is `--future-deprecation=import`, which will emit warnings for
Sass `@import` rules, which are not yet deprecated, but will be in the future.

### Dart API

* New `Deprecation` enum, which contains the different current and future
deprecations used by the new CLI flags.

* The `compile` methods now take in `fatalDeprecations` and `futureDeprecations`
parameters, which work similarly to the CLI flags.

## 1.58.4

* Pull `@font-face` to the root rather than bubbling the style rule selector
Expand Down
14 changes: 12 additions & 2 deletions bin/sass.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:sass/src/executable/repl.dart';
import 'package:sass/src/executable/watch.dart';
import 'package:sass/src/import_cache.dart';
import 'package:sass/src/io.dart';
import 'package:sass/src/logger/deprecation_handling.dart';
import 'package:sass/src/stylesheet_graph.dart';
import 'package:sass/src/utils.dart';

Expand Down Expand Up @@ -52,8 +53,17 @@ Future<void> main(List<String> args) async {
return;
}

var graph = StylesheetGraph(
ImportCache(loadPaths: options.loadPaths, logger: options.logger));
var graph = StylesheetGraph(ImportCache(
loadPaths: options.loadPaths,
// This logger is only used for handling fatal/future deprecations
// during parsing, and is re-used across parses, so we don't want to
// limit repetition. A separate DeprecationHandlingLogger is created for
// each compilation, which will limit repetition if verbose is not
// passed in addition to handling fatal/future deprecations.
logger: DeprecationHandlingLogger(options.logger,
fatalDeprecations: options.fatalDeprecations,
futureDeprecations: options.futureDeprecations,
limitRepetition: false)));
if (options.watch) {
await watch(options, graph);
return;
Expand Down
32 changes: 24 additions & 8 deletions lib/sass.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'src/async_import_cache.dart';
import 'src/callable.dart';
import 'src/compile.dart' as c;
import 'src/compile_result.dart';
import 'src/deprecation.dart';
import 'src/exception.dart';
import 'src/import_cache.dart';
import 'src/importer.dart';
Expand All @@ -24,9 +25,10 @@ import 'src/visitor/serialize.dart';

export 'src/callable.dart' show Callable, AsyncCallable;
export 'src/compile_result.dart';
export 'src/deprecation.dart';
export 'src/exception.dart' show SassException;
export 'src/importer.dart';
export 'src/logger.dart';
export 'src/logger.dart' show Logger;
export 'src/syntax.dart';
export 'src/value.dart'
hide ColorFormat, SassApiColor, SassApiValue, SpanColorFormat;
Expand Down Expand Up @@ -105,7 +107,9 @@ CompileResult compileToResult(String path,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) =>
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compile(path,
logger: logger,
importCache: ImportCache(
Expand All @@ -118,7 +122,9 @@ CompileResult compileToResult(String path,
quietDeps: quietDeps,
verbose: verbose,
sourceMap: sourceMap,
charset: charset);
charset: charset,
fatalDeprecations: fatalDeprecations,
futureDeprecations: futureDeprecations);

/// Compiles [source] to CSS and returns a [CompileResult] containing the CSS
/// and additional metadata about the compilation..
Expand Down Expand Up @@ -200,7 +206,9 @@ CompileResult compileStringToResult(String source,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) =>
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compileString(source,
syntax: syntax,
logger: logger,
Expand All @@ -216,7 +224,9 @@ CompileResult compileStringToResult(String source,
quietDeps: quietDeps,
verbose: verbose,
sourceMap: sourceMap,
charset: charset);
charset: charset,
fatalDeprecations: fatalDeprecations,
futureDeprecations: futureDeprecations);

/// Like [compileToResult], except it runs asynchronously.
///
Expand All @@ -234,7 +244,9 @@ Future<CompileResult> compileToResultAsync(String path,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) =>
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compileAsync(path,
logger: logger,
importCache: AsyncImportCache(
Expand All @@ -247,7 +259,9 @@ Future<CompileResult> compileToResultAsync(String path,
quietDeps: quietDeps,
verbose: verbose,
sourceMap: sourceMap,
charset: charset);
charset: charset,
fatalDeprecations: fatalDeprecations,
futureDeprecations: futureDeprecations);

/// Like [compileStringToResult], except it runs asynchronously.
///
Expand All @@ -270,7 +284,9 @@ Future<CompileResult> compileStringToResultAsync(String source,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) =>
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compileStringAsync(source,
syntax: syntax,
logger: logger,
Expand Down
5 changes: 3 additions & 2 deletions lib/src/ast/selector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'package:meta/meta.dart';
import 'package:source_span/source_span.dart';

import '../deprecation.dart';
import '../evaluation_context.dart';
import '../exception.dart';
import '../visitor/any_selector.dart';
Expand Down Expand Up @@ -88,13 +89,13 @@ abstract class Selector implements AstNode {
/// throw a [SassException] in Dart Sass 2.0.0.
void assertNotBogus({String? name}) {
if (!isBogus) return;
warn(
warnForDeprecation(
(name == null ? '' : '\$$name: ') +
'$this is not valid CSS.\n'
'This will be an error in Dart Sass 2.0.0.\n'
'\n'
'More info: https://sass-lang.com/d/bogus-combinators',
deprecation: true);
Deprecation.bogusCombinators);
}

/// Calls the appropriate visit method on [visitor].
Expand Down
29 changes: 20 additions & 9 deletions lib/src/async_compile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import 'ast/sass.dart';
import 'async_import_cache.dart';
import 'callable.dart';
import 'compile_result.dart';
import 'deprecation.dart';
import 'importer.dart';
import 'importer/legacy_node.dart';
import 'io.dart';
import 'logger.dart';
import 'logger/terse.dart';
import 'logger/deprecation_handling.dart';
import 'syntax.dart';
import 'utils.dart';
import 'visitor/async_evaluate.dart';
Expand All @@ -37,9 +38,14 @@ Future<CompileResult> compileAsync(String path,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) async {
TerseLogger? terseLogger;
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) async {
DeprecationHandlingLogger deprecationLogger = logger =
DeprecationHandlingLogger(logger ?? Logger.stderr(),
fatalDeprecations: {...?fatalDeprecations},
futureDeprecations: {...?futureDeprecations},
limitRepetition: !verbose);

// If the syntax is different than the importer would default to, we have to
// parse the file manually and we can't store it in the cache.
Expand Down Expand Up @@ -71,7 +77,7 @@ Future<CompileResult> compileAsync(String path,
sourceMap,
charset);

terseLogger?.summarize(node: nodeImporter != null);
deprecationLogger.summarize(node: nodeImporter != null);
return result;
}

Expand All @@ -96,9 +102,14 @@ Future<CompileResult> compileStringAsync(String source,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) async {
TerseLogger? terseLogger;
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) async {
DeprecationHandlingLogger deprecationLogger = logger =
DeprecationHandlingLogger(logger ?? Logger.stderr(),
fatalDeprecations: {...?fatalDeprecations},
futureDeprecations: {...?futureDeprecations},
limitRepetition: !verbose);

var stylesheet =
Stylesheet.parse(source, syntax ?? Syntax.scss, url: url, logger: logger);
Expand All @@ -118,7 +129,7 @@ Future<CompileResult> compileStringAsync(String source,
sourceMap,
charset);

terseLogger?.summarize(node: nodeImporter != null);
deprecationLogger.summarize(node: nodeImporter != null);
return result;
}

Expand Down
5 changes: 3 additions & 2 deletions lib/src/async_import_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:path/path.dart' as p;
import 'package:tuple/tuple.dart';

import 'ast/sass.dart';
import 'deprecation.dart';
import 'importer.dart';
import 'importer/utils.dart';
import 'io.dart';
Expand Down Expand Up @@ -154,10 +155,10 @@ class AsyncImportCache {
? inImportRule(() => importer.canonicalize(url))
: importer.canonicalize(url));
if (result?.scheme == '') {
_logger.warn("""
_logger.warnForDeprecation(Deprecation.relativeCanonical, """
Importer $importer canonicalized $url to $result.
Relative canonical URLs are deprecated and will eventually be disallowed.
""", deprecation: true);
""");
}
return result;
}
Expand Down
31 changes: 21 additions & 10 deletions lib/src/compile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_compile.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: f8b5bf7eafbe3523ca4df1a6832e131c5c03986b
// Checksum: 628fbfe8a6717cca332dd646eeda2260dd3e30c6
//
// ignore_for_file: unused_import

Expand All @@ -19,11 +19,12 @@ import 'ast/sass.dart';
import 'import_cache.dart';
import 'callable.dart';
import 'compile_result.dart';
import 'deprecation.dart';
import 'importer.dart';
import 'importer/legacy_node.dart';
import 'io.dart';
import 'logger.dart';
import 'logger/terse.dart';
import 'logger/deprecation_handling.dart';
import 'syntax.dart';
import 'utils.dart';
import 'visitor/evaluate.dart';
Expand All @@ -46,9 +47,14 @@ CompileResult compile(String path,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) {
TerseLogger? terseLogger;
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) {
DeprecationHandlingLogger deprecationLogger = logger =
DeprecationHandlingLogger(logger ?? Logger.stderr(),
fatalDeprecations: {...?fatalDeprecations},
futureDeprecations: {...?futureDeprecations},
limitRepetition: !verbose);

// If the syntax is different than the importer would default to, we have to
// parse the file manually and we can't store it in the cache.
Expand Down Expand Up @@ -80,7 +86,7 @@ CompileResult compile(String path,
sourceMap,
charset);

terseLogger?.summarize(node: nodeImporter != null);
deprecationLogger.summarize(node: nodeImporter != null);
return result;
}

Expand All @@ -105,9 +111,14 @@ CompileResult compileString(String source,
bool quietDeps = false,
bool verbose = false,
bool sourceMap = false,
bool charset = true}) {
TerseLogger? terseLogger;
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
bool charset = true,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) {
DeprecationHandlingLogger deprecationLogger = logger =
DeprecationHandlingLogger(logger ?? Logger.stderr(),
fatalDeprecations: {...?fatalDeprecations},
futureDeprecations: {...?futureDeprecations},
limitRepetition: !verbose);

var stylesheet =
Stylesheet.parse(source, syntax ?? Syntax.scss, url: url, logger: logger);
Expand All @@ -127,7 +138,7 @@ CompileResult compileString(String source,
sourceMap,
charset);

terseLogger?.summarize(node: nodeImporter != null);
deprecationLogger.summarize(node: nodeImporter != null);
return result;
}

Expand Down

0 comments on commit 8f8138d

Please sign in to comment.