Skip to content

Commit d67f341

Browse files
committed
Indicate the original configuration location for multi-config errors
1 parent c2baede commit d67f341

File tree

5 files changed

+48
-19
lines changed

5 files changed

+48
-19
lines changed

lib/src/async_environment.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ class AsyncEnvironment {
799799
configuration[name] = ConfiguredValue(values[name], null, nodes[name]);
800800
}
801801
}
802-
return Configuration(configuration, isImplicit: true);
802+
return Configuration.implicit(configuration);
803803
}
804804

805805
/// Returns a module that represents the top-level members defined in [this],

lib/src/configuration.dart

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:collection';
66

7+
import 'ast/node.dart';
78
import 'ast/sass.dart';
89
import 'configured_value.dart';
910
import 'util/limited_map_view.dart';
@@ -19,6 +20,11 @@ class Configuration {
1920
Map<String, ConfiguredValue> get values => UnmodifiableMapView(_values);
2021
final Map<String, ConfiguredValue> _values;
2122

23+
/// The node whose span indicates where the configuration was declared.
24+
///
25+
/// This is `null` for implicit configurations.
26+
final AstNode nodeWithSpan;
27+
2228
/// Whether or not this configuration is implicit.
2329
///
2430
/// Implicit configurations are created when a file containing a `@forward`
@@ -31,8 +37,18 @@ class Configuration {
3137
/// silently ignored in this case.
3238
final bool isImplicit;
3339

34-
Configuration(Map<String, ConfiguredValue> values, {this.isImplicit = false})
35-
: _values = values;
40+
/// Creates an explicit configuration with the given [values].
41+
Configuration(Map<String, ConfiguredValue> values, this.nodeWithSpan)
42+
: _values = values,
43+
isImplicit = false;
44+
45+
/// Creates an implicit configuration with the given [values].
46+
///
47+
/// See [isImplicit] for details.
48+
Configuration.implicit(Map<String, ConfiguredValue> values)
49+
: _values = values,
50+
nodeWithSpan = null,
51+
isImplicit = true;
3652

3753
/// The empty configuration, which indicates that the module has not been
3854
/// configured.
@@ -41,6 +57,7 @@ class Configuration {
4157
/// ignored if the module has already been loaded.
4258
const Configuration.empty()
4359
: _values = const {},
60+
nodeWithSpan = null,
4461
isImplicit = true;
4562

4663
bool get isEmpty => values.isEmpty;
@@ -67,6 +84,8 @@ class Configuration {
6784
} else if (forward.hiddenVariables?.isNotEmpty ?? false) {
6885
newValues = LimitedMapView.blocklist(newValues, forward.hiddenVariables);
6986
}
70-
return Configuration(newValues, isImplicit: isImplicit);
87+
return isImplicit
88+
? Configuration.implicit(newValues)
89+
: Configuration(newValues, nodeWithSpan);
7190
}
7291
}

lib/src/environment.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// DO NOT EDIT. This file was generated from async_environment.dart.
66
// See tool/grind/synchronize.dart for details.
77
//
8-
// Checksum: 6e375d7e8ccaafe80c33ec5a220bc4acf5dbc3d0
8+
// Checksum: e0f39c1b98cb2adf98116bd51bf03d492be953c3
99
//
1010
// ignore_for_file: unused_import
1111

@@ -804,7 +804,7 @@ class Environment {
804804
configuration[name] = ConfiguredValue(values[name], null, nodes[name]);
805805
}
806806
}
807-
return Configuration(configuration, isImplicit: true);
807+
return Configuration.implicit(configuration);
808808
}
809809

810810
/// Returns a module that represents the top-level members defined in [this],

lib/src/visitor/async_evaluate.dart

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ class _EvaluateVisitor
437437

438438
values[name] = ConfiguredValue(value, span);
439439
});
440-
configuration = Configuration(values);
440+
configuration = Configuration(values, _callableNode);
441441
}
442442

443443
await _loadModule(url, "load-css()", _callableNode,
@@ -625,10 +625,15 @@ class _EvaluateVisitor
625625
"\"with\".";
626626

627627
var existingNode = _moduleNodes[url];
628-
throw existingNode == null
628+
var secondarySpans = {
629+
if (existingNode != null) existingNode.span: "original load",
630+
if (configuration == null)
631+
_configuration.nodeWithSpan.span: "configuration"
632+
};
633+
634+
throw secondarySpans.isEmpty
629635
? _exception(message)
630-
: _multiSpanException(
631-
message, "new load", {existingNode.span: "original load"});
636+
: _multiSpanException(message, "new load", secondarySpans);
632637
}
633638

634639
return alreadyLoaded;
@@ -1274,7 +1279,7 @@ class _EvaluateVisitor
12741279
_expressionNode(variable.expression));
12751280
}
12761281

1277-
return Configuration(newValues);
1282+
return Configuration(newValues, node);
12781283
}
12791284

12801285
/// Remove configured values from [upstream] that have been removed from
@@ -1876,7 +1881,7 @@ class _EvaluateVisitor
18761881
(await variable.expression.accept(this)).withoutSlash(),
18771882
variable.span,
18781883
_expressionNode(variable.expression))
1879-
});
1884+
}, node);
18801885

18811886
await _loadModule(node.url, "@use", node, (module) {
18821887
_environment.addModule(module, node, namespace: node.namespace);

lib/src/visitor/evaluate.dart

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

@@ -442,7 +442,7 @@ class _EvaluateVisitor
442442

443443
values[name] = ConfiguredValue(value, span);
444444
});
445-
configuration = Configuration(values);
445+
configuration = Configuration(values, _callableNode);
446446
}
447447

448448
_loadModule(url, "load-css()", _callableNode,
@@ -628,10 +628,15 @@ class _EvaluateVisitor
628628
"\"with\".";
629629

630630
var existingNode = _moduleNodes[url];
631-
throw existingNode == null
631+
var secondarySpans = {
632+
if (existingNode != null) existingNode.span: "original load",
633+
if (configuration == null)
634+
_configuration.nodeWithSpan.span: "configuration"
635+
};
636+
637+
throw secondarySpans.isEmpty
632638
? _exception(message)
633-
: _multiSpanException(
634-
message, "new load", {existingNode.span: "original load"});
639+
: _multiSpanException(message, "new load", secondarySpans);
635640
}
636641

637642
return alreadyLoaded;
@@ -1272,7 +1277,7 @@ class _EvaluateVisitor
12721277
_expressionNode(variable.expression));
12731278
}
12741279

1275-
return Configuration(newValues);
1280+
return Configuration(newValues, node);
12761281
}
12771282

12781283
/// Remove configured values from [upstream] that have been removed from
@@ -1866,7 +1871,7 @@ class _EvaluateVisitor
18661871
variable.expression.accept(this).withoutSlash(),
18671872
variable.span,
18681873
_expressionNode(variable.expression))
1869-
});
1874+
}, node);
18701875

18711876
_loadModule(node.url, "@use", node, (module) {
18721877
_environment.addModule(module, node, namespace: node.namespace);

0 commit comments

Comments
 (0)