Skip to content
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

Enable strict null checks #1283

Merged
merged 19 commits into from Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 18 additions & 10 deletions bin/sass.dart
Expand Up @@ -24,7 +24,7 @@ Future<void> main(List<String> args) async {
// has been printed to stderr.
//
// If [trace] is passed, its terse representation is printed after the error.
void printError(String error, StackTrace stackTrace) {
void printError(String error, StackTrace? stackTrace) {
if (printedError) stderr.writeln();
printedError = true;
stderr.writeln(error);
Expand All @@ -35,7 +35,7 @@ Future<void> main(List<String> args) async {
}
}

ExecutableOptions options;
ExecutableOptions? options;
try {
options = ExecutableOptions.parse(args);
term_glyph.ascii = !options.unicode;
Expand All @@ -52,7 +52,7 @@ Future<void> main(List<String> args) async {
}

var graph = StylesheetGraph(
ImportCache([], loadPaths: options.loadPaths, logger: options.logger));
ImportCache(loadPaths: options.loadPaths, logger: options.logger));
if (options.watch) {
await watch(options, graph);
return;
Expand All @@ -68,7 +68,9 @@ Future<void> main(List<String> args) async {
// dart-lang/sdk#33400.
() {
try {
if (destination != null && !options.emitErrorCss) {
if (destination != null &&
// dart-lang/sdk#45348
!options!.emitErrorCss) {
deleteFile(destination);
}
} on FileSystemException {
Expand All @@ -86,7 +88,11 @@ Future<void> main(List<String> args) async {
if (exitCode != 66) exitCode = 65;
if (options.stopOnError) return;
} on FileSystemException catch (error, stackTrace) {
printError("Error reading ${p.relative(error.path)}: ${error.message}.",
var path = error.path;
printError(
path == null
? error.message
: "Error reading ${p.relative(path)}: ${error.message}.",
options.trace ? stackTrace : null);

// Error 66 indicates no input.
Expand Down Expand Up @@ -115,12 +121,14 @@ Future<void> main(List<String> args) async {

/// Loads and returns the current version of Sass.
Future<String> _loadVersion() async {
var version = const String.fromEnvironment('version');
if (const bool.fromEnvironment('node')) {
version += " compiled with dart2js "
"${const String.fromEnvironment('dart-version')}";
if (const bool.hasEnvironment('version')) {
var version = const String.fromEnvironment('version');
if (const bool.fromEnvironment('node')) {
version += " compiled with dart2js "
"${const String.fromEnvironment('dart-version')}";
}
return version;
}
if (version != null) return version;

var libDir =
p.fromUri(await Isolate.resolvePackageUri(Uri.parse('package:sass/')));
Expand Down
111 changes: 58 additions & 53 deletions lib/sass.dart
Expand Up @@ -5,6 +5,7 @@
/// We strongly recommend importing this library with the prefix `sass`.
library sass;

import 'package:package_config/package_config_types.dart';
import 'package:source_maps/source_maps.dart';

import 'src/async_import_cache.dart';
Expand All @@ -14,8 +15,8 @@ import 'src/exception.dart';
import 'src/import_cache.dart';
import 'src/importer.dart';
import 'src/logger.dart';
import 'src/sync_package_resolver.dart';
import 'src/syntax.dart';
import 'src/util/nullable.dart';
import 'src/visitor/serialize.dart';

export 'src/callable.dart' show Callable, AsyncCallable;
Expand Down Expand Up @@ -48,11 +49,11 @@ export 'src/warn.dart' show warn;
/// * Each load path specified in the `SASS_PATH` environment variable, which
/// should be semicolon-separated on Windows and colon-separated elsewhere.
///
/// * `package:` resolution using [packageResolver], which is a
/// [`SyncPackageResolver`][] from the `package_resolver` package. Note that
/// * `package:` resolution using [packageConfig], which is a
/// [`PackageConfig`][] from the `package_resolver` package. Note that
/// this is a shorthand for adding a [PackageImporter] to [importers].
///
/// [`SyncPackageResolver`]: https://www.dartdocs.org/documentation/package_resolver/latest/package_resolver/SyncPackageResolver-class.html
/// [`PackageConfig`]: https://pub.dev/documentation/package_config/latest/package_config.package_config/PackageConfig-class.html
///
/// Dart functions that can be called from Sass may be passed using [functions].
/// Each [Callable] defines a top-level function that will be invoked when the
Expand Down Expand Up @@ -87,26 +88,27 @@ export 'src/warn.dart' show warn;
/// Throws a [SassException] if conversion fails.
String compile(String path,
{bool color = false,
Logger logger,
Iterable<Importer> importers,
Iterable<String> loadPaths,
SyncPackageResolver packageResolver,
Iterable<Callable> functions,
OutputStyle style,
void sourceMap(SingleMapping map),
Logger? logger,
Iterable<Importer>? importers,
Iterable<String>? loadPaths,
PackageConfig? packageConfig,
Iterable<Callable>? functions,
OutputStyle? style,
void sourceMap(SingleMapping map)?,
bool charset = true}) {
logger ??= Logger.stderr(color: color);
var result = c.compile(path,
logger: logger,
importCache: ImportCache(importers,
importCache: ImportCache(
importers: importers,
logger: logger,
loadPaths: loadPaths,
packageResolver: packageResolver),
packageConfig: packageConfig),
functions: functions,
style: style,
sourceMap: sourceMap != null,
charset: charset);
if (sourceMap != null) sourceMap(result.sourceMap);
result.sourceMap.andThen(sourceMap);
return result.css;
}

Expand All @@ -132,11 +134,11 @@ String compile(String path,
/// * Each load path specified in the `SASS_PATH` environment variable, which
/// should be semicolon-separated on Windows and colon-separated elsewhere.
///
/// * `package:` resolution using [packageResolver], which is a
/// [`SyncPackageResolver`][] from the `package_resolver` package. Note that
/// * `package:` resolution using [packageConfig], which is a
/// [`PackageConfig`][] from the `package_resolver` package. Note that
/// this is a shorthand for adding a [PackageImporter] to [importers].
///
/// [`SyncPackageResolver`]: https://www.dartdocs.org/documentation/package_resolver/latest/package_resolver/SyncPackageResolver-class.html
/// [`PackageConfig`]: https://pub.dev/documentation/package_config/latest/package_config.package_config/PackageConfig-class.html
///
/// Dart functions that can be called from Sass may be passed using [functions].
/// Each [Callable] defines a top-level function that will be invoked when the
Expand Down Expand Up @@ -174,34 +176,35 @@ String compile(String path,
///
/// Throws a [SassException] if conversion fails.
String compileString(String source,
{Syntax syntax,
{Syntax? syntax,
bool color = false,
Logger logger,
Iterable<Importer> importers,
SyncPackageResolver packageResolver,
Iterable<String> loadPaths,
Iterable<Callable> functions,
OutputStyle style,
Importer importer,
Object url,
void sourceMap(SingleMapping map),
Logger? logger,
Iterable<Importer>? importers,
PackageConfig? packageConfig,
Iterable<String>? loadPaths,
Iterable<Callable>? functions,
OutputStyle? style,
Importer? importer,
Object? url,
void sourceMap(SingleMapping map)?,
bool charset = true,
@Deprecated("Use syntax instead.") bool indented = false}) {
logger ??= Logger.stderr(color: color);
var result = c.compileString(source,
syntax: syntax ?? (indented ? Syntax.sass : Syntax.scss),
logger: logger,
importCache: ImportCache(importers,
importCache: ImportCache(
importers: importers,
logger: logger,
packageResolver: packageResolver,
packageConfig: packageConfig,
loadPaths: loadPaths),
functions: functions,
style: style,
importer: importer,
url: url,
sourceMap: sourceMap != null,
charset: charset);
if (sourceMap != null) sourceMap(result.sourceMap);
result.sourceMap.andThen(sourceMap);
return result.css;
}

Expand All @@ -212,24 +215,25 @@ String compileString(String source,
/// slower, so [compile] should be preferred if possible.
Future<String> compileAsync(String path,
{bool color = false,
Logger logger,
Iterable<AsyncImporter> importers,
SyncPackageResolver packageResolver,
Iterable<String> loadPaths,
Iterable<AsyncCallable> functions,
OutputStyle style,
void sourceMap(SingleMapping map)}) async {
Logger? logger,
Iterable<AsyncImporter>? importers,
PackageConfig? packageConfig,
Iterable<String>? loadPaths,
Iterable<AsyncCallable>? functions,
OutputStyle? style,
void sourceMap(SingleMapping map)?}) async {
logger ??= Logger.stderr(color: color);
var result = await c.compileAsync(path,
logger: logger,
importCache: AsyncImportCache(importers,
importCache: AsyncImportCache(
importers: importers,
logger: logger,
loadPaths: loadPaths,
packageResolver: packageResolver),
packageConfig: packageConfig),
functions: functions,
style: style,
sourceMap: sourceMap != null);
if (sourceMap != null) sourceMap(result.sourceMap);
result.sourceMap.andThen(sourceMap);
return result.css;
}

Expand All @@ -239,33 +243,34 @@ Future<String> compileAsync(String path,
/// synchronous [Importer]s. However, running asynchronously is also somewhat
/// slower, so [compileString] should be preferred if possible.
Future<String> compileStringAsync(String source,
{Syntax syntax,
{Syntax? syntax,
bool color = false,
Logger logger,
Iterable<AsyncImporter> importers,
SyncPackageResolver packageResolver,
Iterable<String> loadPaths,
Iterable<AsyncCallable> functions,
OutputStyle style,
AsyncImporter importer,
Object url,
void sourceMap(SingleMapping map),
Logger? logger,
Iterable<AsyncImporter>? importers,
PackageConfig? packageConfig,
Iterable<String>? loadPaths,
Iterable<AsyncCallable>? functions,
OutputStyle? style,
AsyncImporter? importer,
Object? url,
void sourceMap(SingleMapping map)?,
bool charset = true,
@Deprecated("Use syntax instead.") bool indented = false}) async {
logger ??= Logger.stderr(color: color);
var result = await c.compileStringAsync(source,
syntax: syntax ?? (indented ? Syntax.sass : Syntax.scss),
logger: logger,
importCache: AsyncImportCache(importers,
importCache: AsyncImportCache(
importers: importers,
logger: logger,
packageResolver: packageResolver,
packageConfig: packageConfig,
loadPaths: loadPaths),
functions: functions,
style: style,
importer: importer,
url: url,
sourceMap: sourceMap != null,
charset: charset);
if (sourceMap != null) sourceMap(result.sourceMap);
result.sourceMap.andThen(sourceMap);
return result.css;
}
2 changes: 1 addition & 1 deletion lib/src/ast/css/at_rule.dart
Expand Up @@ -12,7 +12,7 @@ abstract class CssAtRule extends CssParentNode {
CssValue<String> get name;

/// The value of this rule.
CssValue<String> get value;
CssValue<String>? get value;

/// Whether the rule has no children.
///
Expand Down
4 changes: 2 additions & 2 deletions lib/src/ast/css/import.dart
Expand Up @@ -15,10 +15,10 @@ abstract class CssImport extends CssNode {
CssValue<String> get url;

/// The supports condition attached to this import.
CssValue<String> get supports;
CssValue<String>? get supports;

/// The media query attached to this import.
List<CssMediaQuery> get media;
List<CssMediaQuery>? get media;

T accept<T>(CssVisitor<T> visitor) => visitor.visitCssImport(this);
}
12 changes: 6 additions & 6 deletions lib/src/ast/css/media_query.dart
Expand Up @@ -11,12 +11,12 @@ class CssMediaQuery {
/// The modifier, probably either "not" or "only".
///
/// This may be `null` if no modifier is in use.
final String modifier;
final String? modifier;

/// The media type, for example "screen" or "print".
///
/// This may be `null`. If so, [features] will not be empty.
final String type;
final String? type;

/// Feature queries, including parentheses.
final List<String> features;
Expand All @@ -33,11 +33,11 @@ class CssMediaQuery {
///
/// Throws a [SassFormatException] if parsing fails.
static List<CssMediaQuery> parseList(String contents,
{Object url, Logger logger}) =>
{Object? url, Logger? logger}) =>
MediaQueryParser(contents, url: url, logger: logger).parse();

/// Creates a media query specifies a type and, optionally, features.
CssMediaQuery(this.type, {this.modifier, Iterable<String> features})
CssMediaQuery(this.type, {this.modifier, Iterable<String>? features})
: features = features == null ? const [] : List.unmodifiable(features);

/// Creates a media query that only specifies features.
Expand All @@ -59,8 +59,8 @@ class CssMediaQuery {
CssMediaQuery.condition([...this.features, ...other.features]));
}

String modifier;
String type;
String? modifier;
String? type;
List<String> features;
if ((ourModifier == 'not') != (theirModifier == 'not')) {
if (ourType == theirType) {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/at_rule.dart
Expand Up @@ -12,7 +12,7 @@ import 'node.dart';
/// A modifiable version of [CssAtRule] for use in the evaluation step.
class ModifiableCssAtRule extends ModifiableCssParentNode implements CssAtRule {
final CssValue<String> name;
final CssValue<String> value;
final CssValue<String>? value;
final bool isChildless;
final FileSpan span;

Expand Down
5 changes: 2 additions & 3 deletions lib/src/ast/css/modifiable/declaration.dart
Expand Up @@ -2,7 +2,6 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

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

import '../../../value.dart';
Expand All @@ -24,9 +23,9 @@ class ModifiableCssDeclaration extends ModifiableCssNode

/// Returns a new CSS declaration with the given properties.
ModifiableCssDeclaration(this.name, this.value, this.span,
{@required bool parsedAsCustomProperty, FileSpan valueSpanForMap})
{required bool parsedAsCustomProperty, FileSpan? valueSpanForMap})
: parsedAsCustomProperty = parsedAsCustomProperty,
valueSpanForMap = valueSpanForMap ?? span {
valueSpanForMap = valueSpanForMap ?? value.span {
if (parsedAsCustomProperty) {
if (!isCustomProperty) {
throw ArgumentError(
Expand Down
6 changes: 3 additions & 3 deletions lib/src/ast/css/modifiable/import.dart
Expand Up @@ -18,15 +18,15 @@ class ModifiableCssImport extends ModifiableCssNode implements CssImport {
final CssValue<String> url;

/// The supports condition attached to this import.
final CssValue<String> supports;
final CssValue<String>? supports;

/// The media query attached to this import.
final List<CssMediaQuery> media;
final List<CssMediaQuery>? media;

final FileSpan span;

ModifiableCssImport(this.url, this.span,
{this.supports, Iterable<CssMediaQuery> media})
{this.supports, Iterable<CssMediaQuery>? media})
: media = media == null ? null : List.unmodifiable(media);

T accept<T>(ModifiableCssVisitor<T> visitor) => visitor.visitCssImport(this);
Expand Down