Skip to content

Commit 8f8138d

Browse files
authored
Add --fatal-deprecations and --future-deprecations (#1820)
* 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
1 parent 9417b6e commit 8f8138d

27 files changed

+731
-173
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
## 1.59.0
2+
3+
### Command Line Interface
4+
5+
* Added a new `--fatal-deprecation` flag that lets you treat a deprecation
6+
warning as an error. You can pass an individual deprecation ID
7+
(e.g. `slash-div`) or you can pass a Dart Sass version to treat all
8+
deprecations initially emitted in that version or earlier as errors.
9+
10+
* New `--future-deprecation` flag that lets you opt into warning for use of
11+
certain features that will be deprecated in the future. At the moment, the
12+
only option is `--future-deprecation=import`, which will emit warnings for
13+
Sass `@import` rules, which are not yet deprecated, but will be in the future.
14+
15+
### Dart API
16+
17+
* New `Deprecation` enum, which contains the different current and future
18+
deprecations used by the new CLI flags.
19+
20+
* The `compile` methods now take in `fatalDeprecations` and `futureDeprecations`
21+
parameters, which work similarly to the CLI flags.
22+
123
## 1.58.4
224

325
* Pull `@font-face` to the root rather than bubbling the style rule selector

bin/sass.dart

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:sass/src/executable/repl.dart';
1515
import 'package:sass/src/executable/watch.dart';
1616
import 'package:sass/src/import_cache.dart';
1717
import 'package:sass/src/io.dart';
18+
import 'package:sass/src/logger/deprecation_handling.dart';
1819
import 'package:sass/src/stylesheet_graph.dart';
1920
import 'package:sass/src/utils.dart';
2021

@@ -52,8 +53,17 @@ Future<void> main(List<String> args) async {
5253
return;
5354
}
5455

55-
var graph = StylesheetGraph(
56-
ImportCache(loadPaths: options.loadPaths, logger: options.logger));
56+
var graph = StylesheetGraph(ImportCache(
57+
loadPaths: options.loadPaths,
58+
// This logger is only used for handling fatal/future deprecations
59+
// during parsing, and is re-used across parses, so we don't want to
60+
// limit repetition. A separate DeprecationHandlingLogger is created for
61+
// each compilation, which will limit repetition if verbose is not
62+
// passed in addition to handling fatal/future deprecations.
63+
logger: DeprecationHandlingLogger(options.logger,
64+
fatalDeprecations: options.fatalDeprecations,
65+
futureDeprecations: options.futureDeprecations,
66+
limitRepetition: false)));
5767
if (options.watch) {
5868
await watch(options, graph);
5969
return;

lib/sass.dart

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'src/async_import_cache.dart';
1313
import 'src/callable.dart';
1414
import 'src/compile.dart' as c;
1515
import 'src/compile_result.dart';
16+
import 'src/deprecation.dart';
1617
import 'src/exception.dart';
1718
import 'src/import_cache.dart';
1819
import 'src/importer.dart';
@@ -24,9 +25,10 @@ import 'src/visitor/serialize.dart';
2425

2526
export 'src/callable.dart' show Callable, AsyncCallable;
2627
export 'src/compile_result.dart';
28+
export 'src/deprecation.dart';
2729
export 'src/exception.dart' show SassException;
2830
export 'src/importer.dart';
29-
export 'src/logger.dart';
31+
export 'src/logger.dart' show Logger;
3032
export 'src/syntax.dart';
3133
export 'src/value.dart'
3234
hide ColorFormat, SassApiColor, SassApiValue, SpanColorFormat;
@@ -105,7 +107,9 @@ CompileResult compileToResult(String path,
105107
bool quietDeps = false,
106108
bool verbose = false,
107109
bool sourceMap = false,
108-
bool charset = true}) =>
110+
bool charset = true,
111+
Iterable<Deprecation>? fatalDeprecations,
112+
Iterable<Deprecation>? futureDeprecations}) =>
109113
c.compile(path,
110114
logger: logger,
111115
importCache: ImportCache(
@@ -118,7 +122,9 @@ CompileResult compileToResult(String path,
118122
quietDeps: quietDeps,
119123
verbose: verbose,
120124
sourceMap: sourceMap,
121-
charset: charset);
125+
charset: charset,
126+
fatalDeprecations: fatalDeprecations,
127+
futureDeprecations: futureDeprecations);
122128

123129
/// Compiles [source] to CSS and returns a [CompileResult] containing the CSS
124130
/// and additional metadata about the compilation..
@@ -200,7 +206,9 @@ CompileResult compileStringToResult(String source,
200206
bool quietDeps = false,
201207
bool verbose = false,
202208
bool sourceMap = false,
203-
bool charset = true}) =>
209+
bool charset = true,
210+
Iterable<Deprecation>? fatalDeprecations,
211+
Iterable<Deprecation>? futureDeprecations}) =>
204212
c.compileString(source,
205213
syntax: syntax,
206214
logger: logger,
@@ -216,7 +224,9 @@ CompileResult compileStringToResult(String source,
216224
quietDeps: quietDeps,
217225
verbose: verbose,
218226
sourceMap: sourceMap,
219-
charset: charset);
227+
charset: charset,
228+
fatalDeprecations: fatalDeprecations,
229+
futureDeprecations: futureDeprecations);
220230

221231
/// Like [compileToResult], except it runs asynchronously.
222232
///
@@ -234,7 +244,9 @@ Future<CompileResult> compileToResultAsync(String path,
234244
bool quietDeps = false,
235245
bool verbose = false,
236246
bool sourceMap = false,
237-
bool charset = true}) =>
247+
bool charset = true,
248+
Iterable<Deprecation>? fatalDeprecations,
249+
Iterable<Deprecation>? futureDeprecations}) =>
238250
c.compileAsync(path,
239251
logger: logger,
240252
importCache: AsyncImportCache(
@@ -247,7 +259,9 @@ Future<CompileResult> compileToResultAsync(String path,
247259
quietDeps: quietDeps,
248260
verbose: verbose,
249261
sourceMap: sourceMap,
250-
charset: charset);
262+
charset: charset,
263+
fatalDeprecations: fatalDeprecations,
264+
futureDeprecations: futureDeprecations);
251265

252266
/// Like [compileStringToResult], except it runs asynchronously.
253267
///
@@ -270,7 +284,9 @@ Future<CompileResult> compileStringToResultAsync(String source,
270284
bool quietDeps = false,
271285
bool verbose = false,
272286
bool sourceMap = false,
273-
bool charset = true}) =>
287+
bool charset = true,
288+
Iterable<Deprecation>? fatalDeprecations,
289+
Iterable<Deprecation>? futureDeprecations}) =>
274290
c.compileStringAsync(source,
275291
syntax: syntax,
276292
logger: logger,

lib/src/ast/selector.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:meta/meta.dart';
66
import 'package:source_span/source_span.dart';
77

8+
import '../deprecation.dart';
89
import '../evaluation_context.dart';
910
import '../exception.dart';
1011
import '../visitor/any_selector.dart';
@@ -88,13 +89,13 @@ abstract class Selector implements AstNode {
8889
/// throw a [SassException] in Dart Sass 2.0.0.
8990
void assertNotBogus({String? name}) {
9091
if (!isBogus) return;
91-
warn(
92+
warnForDeprecation(
9293
(name == null ? '' : '\$$name: ') +
9394
'$this is not valid CSS.\n'
9495
'This will be an error in Dart Sass 2.0.0.\n'
9596
'\n'
9697
'More info: https://sass-lang.com/d/bogus-combinators',
97-
deprecation: true);
98+
Deprecation.bogusCombinators);
9899
}
99100

100101
/// Calls the appropriate visit method on [visitor].

lib/src/async_compile.dart

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import 'ast/sass.dart';
1010
import 'async_import_cache.dart';
1111
import 'callable.dart';
1212
import 'compile_result.dart';
13+
import 'deprecation.dart';
1314
import 'importer.dart';
1415
import 'importer/legacy_node.dart';
1516
import 'io.dart';
1617
import 'logger.dart';
17-
import 'logger/terse.dart';
18+
import 'logger/deprecation_handling.dart';
1819
import 'syntax.dart';
1920
import 'utils.dart';
2021
import 'visitor/async_evaluate.dart';
@@ -37,9 +38,14 @@ Future<CompileResult> compileAsync(String path,
3738
bool quietDeps = false,
3839
bool verbose = false,
3940
bool sourceMap = false,
40-
bool charset = true}) async {
41-
TerseLogger? terseLogger;
42-
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
41+
bool charset = true,
42+
Iterable<Deprecation>? fatalDeprecations,
43+
Iterable<Deprecation>? futureDeprecations}) async {
44+
DeprecationHandlingLogger deprecationLogger = logger =
45+
DeprecationHandlingLogger(logger ?? Logger.stderr(),
46+
fatalDeprecations: {...?fatalDeprecations},
47+
futureDeprecations: {...?futureDeprecations},
48+
limitRepetition: !verbose);
4349

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

74-
terseLogger?.summarize(node: nodeImporter != null);
80+
deprecationLogger.summarize(node: nodeImporter != null);
7581
return result;
7682
}
7783

@@ -96,9 +102,14 @@ Future<CompileResult> compileStringAsync(String source,
96102
bool quietDeps = false,
97103
bool verbose = false,
98104
bool sourceMap = false,
99-
bool charset = true}) async {
100-
TerseLogger? terseLogger;
101-
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
105+
bool charset = true,
106+
Iterable<Deprecation>? fatalDeprecations,
107+
Iterable<Deprecation>? futureDeprecations}) async {
108+
DeprecationHandlingLogger deprecationLogger = logger =
109+
DeprecationHandlingLogger(logger ?? Logger.stderr(),
110+
fatalDeprecations: {...?fatalDeprecations},
111+
futureDeprecations: {...?futureDeprecations},
112+
limitRepetition: !verbose);
102113

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

121-
terseLogger?.summarize(node: nodeImporter != null);
132+
deprecationLogger.summarize(node: nodeImporter != null);
122133
return result;
123134
}
124135

lib/src/async_import_cache.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:path/path.dart' as p;
99
import 'package:tuple/tuple.dart';
1010

1111
import 'ast/sass.dart';
12+
import 'deprecation.dart';
1213
import 'importer.dart';
1314
import 'importer/utils.dart';
1415
import 'io.dart';
@@ -154,10 +155,10 @@ class AsyncImportCache {
154155
? inImportRule(() => importer.canonicalize(url))
155156
: importer.canonicalize(url));
156157
if (result?.scheme == '') {
157-
_logger.warn("""
158+
_logger.warnForDeprecation(Deprecation.relativeCanonical, """
158159
Importer $importer canonicalized $url to $result.
159160
Relative canonical URLs are deprecated and will eventually be disallowed.
160-
""", deprecation: true);
161+
""");
161162
}
162163
return result;
163164
}

lib/src/compile.dart

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// DO NOT EDIT. This file was generated from async_compile.dart.
66
// See tool/grind/synchronize.dart for details.
77
//
8-
// Checksum: f8b5bf7eafbe3523ca4df1a6832e131c5c03986b
8+
// Checksum: 628fbfe8a6717cca332dd646eeda2260dd3e30c6
99
//
1010
// ignore_for_file: unused_import
1111

@@ -19,11 +19,12 @@ import 'ast/sass.dart';
1919
import 'import_cache.dart';
2020
import 'callable.dart';
2121
import 'compile_result.dart';
22+
import 'deprecation.dart';
2223
import 'importer.dart';
2324
import 'importer/legacy_node.dart';
2425
import 'io.dart';
2526
import 'logger.dart';
26-
import 'logger/terse.dart';
27+
import 'logger/deprecation_handling.dart';
2728
import 'syntax.dart';
2829
import 'utils.dart';
2930
import 'visitor/evaluate.dart';
@@ -46,9 +47,14 @@ CompileResult compile(String path,
4647
bool quietDeps = false,
4748
bool verbose = false,
4849
bool sourceMap = false,
49-
bool charset = true}) {
50-
TerseLogger? terseLogger;
51-
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
50+
bool charset = true,
51+
Iterable<Deprecation>? fatalDeprecations,
52+
Iterable<Deprecation>? futureDeprecations}) {
53+
DeprecationHandlingLogger deprecationLogger = logger =
54+
DeprecationHandlingLogger(logger ?? Logger.stderr(),
55+
fatalDeprecations: {...?fatalDeprecations},
56+
futureDeprecations: {...?futureDeprecations},
57+
limitRepetition: !verbose);
5258

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

83-
terseLogger?.summarize(node: nodeImporter != null);
89+
deprecationLogger.summarize(node: nodeImporter != null);
8490
return result;
8591
}
8692

@@ -105,9 +111,14 @@ CompileResult compileString(String source,
105111
bool quietDeps = false,
106112
bool verbose = false,
107113
bool sourceMap = false,
108-
bool charset = true}) {
109-
TerseLogger? terseLogger;
110-
if (!verbose) logger = terseLogger = TerseLogger(logger ?? Logger.stderr());
114+
bool charset = true,
115+
Iterable<Deprecation>? fatalDeprecations,
116+
Iterable<Deprecation>? futureDeprecations}) {
117+
DeprecationHandlingLogger deprecationLogger = logger =
118+
DeprecationHandlingLogger(logger ?? Logger.stderr(),
119+
fatalDeprecations: {...?fatalDeprecations},
120+
futureDeprecations: {...?futureDeprecations},
121+
limitRepetition: !verbose);
111122

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

130-
terseLogger?.summarize(node: nodeImporter != null);
141+
deprecationLogger.summarize(node: nodeImporter != null);
131142
return result;
132143
}
133144

0 commit comments

Comments
 (0)