Skip to content

Commit

Permalink
use object references as opaque ID instead of a randomly generated st…
Browse files Browse the repository at this point in the history
…ring
  • Loading branch information
Goodwine committed Aug 17, 2022
1 parent 9871c89 commit 7f0330f
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 34 deletions.
66 changes: 46 additions & 20 deletions lib/src/configuration.dart
Expand Up @@ -3,8 +3,6 @@
// https://opensource.org/licenses/MIT.

import 'dart:collection';
import 'package:uuid/uuid.dart';

import 'ast/node.dart';
import 'ast/sass.dart';
import 'configured_value.dart';
Expand All @@ -28,21 +26,32 @@ class Configuration {
final Map<String, ConfiguredValue> _values;

/// Creates an implicit configuration with the given [values].
Configuration.implicit(this._values, {String? opaqueId})
: opaqueId = opaqueId ?? Uuid().v1();
Configuration.implicit(this._values) : _originalConfiguration = null;

/// Reference to the original configuration serving as an opaque ID.
final Configuration? _originalConfiguration;

/// Uniquely identifying ID for a configuration lasting across the execution
/// context.
/// Returns whether [this] and [that] [Configuration]s have the same
/// [_originalConfiguration].
///
/// Implicit configurations will always have different IDs.
final String opaqueId;
/// An implicit configuration will always return `false` because it was not
/// created through another configuration.
///
/// [ExplicitConfiguration]s will and configurations created [throughForward]
/// will be considered to have the same original config if they were created
/// as a copy from the same base configuration.
bool sameOriginal(Configuration that) =>
_originalConfiguration != null &&
_originalConfiguration == that._originalConfiguration;

/// The empty configuration, which indicates that the module has not been
/// configured.
///
/// Empty configurations are always considered implicit, since they are
/// ignored if the module has already been loaded.
factory Configuration.empty() => Configuration.implicit({});
const Configuration.empty()
: _values = const {},
_originalConfiguration = null;

bool get isEmpty => values.isEmpty;

Expand All @@ -53,7 +62,7 @@ class Configuration {

/// Creates a new configuration from this one based on a `@forward` rule.
Configuration throughForward(ForwardRule forward) {
if (isEmpty) return Configuration.empty();
if (isEmpty) return const Configuration.empty();
var newValues = _values;

// Only allow variables that are visible through the `@forward` to be
Expand All @@ -70,14 +79,21 @@ class Configuration {
} else if (hiddenVariables != null && hiddenVariables.isNotEmpty) {
newValues = LimitedMapView.blocklist(newValues, hiddenVariables);
}
return _withValues(newValues, opaqueId: opaqueId);
return _copy(newValues);
}

/// Returns a copy of [this] with the given [values] map.
Configuration _withValues(Map<String, ConfiguredValue> values,
{String? opaqueId}) =>
Configuration.implicit(values, opaqueId: opaqueId);
///
/// The copy will have the same [_originalConfiguration] as [this] config.
/// If the original config was `null` [this] will become the original config.
Configuration _copy(Map<String, ConfiguredValue> values) =>
Configuration._(values, _originalConfiguration);

/// Creates a [Configuration] with the given [_values] map and an
/// [_originalConfiguration] reference.
Configuration._(this._values, this._originalConfiguration);

@override
String toString() =>
"(" +
values.entries
Expand All @@ -97,13 +113,23 @@ class ExplicitConfiguration extends Configuration {
/// The node whose span indicates where the configuration was declared.
final AstNode nodeWithSpan;

ExplicitConfiguration(Map<String, ConfiguredValue> values, this.nodeWithSpan,
{String? opaqueId})
: super.implicit(values, opaqueId: opaqueId);
/// Creates a base [ExplicitConfiguration] with a [values] map and a
/// [nodeWithSpan].
ExplicitConfiguration(Map<String, ConfiguredValue> values, this.nodeWithSpan)
: super.implicit(values);

/// Creates an [ExplicitConfiguration] with a [values] map, a [nodeWithSpan]
/// and if this is a copy a reference to the [_originalConfiguration].
ExplicitConfiguration._(Map<String, ConfiguredValue> values,
this.nodeWithSpan, Configuration? originalConfiguration)
: super._(values, originalConfiguration);

/// Returns a copy of [this] with the given [values] map.
///
/// The copy will have the same [_originalConfiguration] as [this] config.
/// If the original config was `null` [this] will become the original config.
@override
Configuration _withValues(Map<String, ConfiguredValue> values,
{String? opaqueId}) =>
ExplicitConfiguration(values, nodeWithSpan, opaqueId: opaqueId);
Configuration _copy(Map<String, ConfiguredValue> values) =>
ExplicitConfiguration._(
values, nodeWithSpan, _originalConfiguration ?? this);
}
11 changes: 5 additions & 6 deletions lib/src/visitor/async_evaluate.dart
Expand Up @@ -141,7 +141,7 @@ class _EvaluateVisitor
/// All modules that have been loaded and evaluated so far.
final _modules = <Uri, Module>{};

/// Configuration seen by a module URI.
/// The first [Configuration] used to load a module [Uri].
final _moduleConfigurations = <Uri, Configuration>{};

/// A map from canonical module URLs to the nodes whose spans indicate where
Expand Down Expand Up @@ -305,7 +305,7 @@ class _EvaluateVisitor
/// The configuration for the current module.
///
/// If this is empty, that indicates that the current module is not configured.
var _configuration = Configuration.empty();
var _configuration = const Configuration.empty();

/// Creates a new visitor.
///
Expand Down Expand Up @@ -470,7 +470,7 @@ class _EvaluateVisitor
var withMap = arguments[1].realNull?.assertMap("with").contents;

var callableNode = _callableNode!;
var configuration = Configuration.empty();
var configuration = const Configuration.empty();
if (withMap != null) {
var values = <String, ConfiguredValue>{};
var span = callableNode.span;
Expand Down Expand Up @@ -673,8 +673,7 @@ class _EvaluateVisitor
var alreadyLoaded = _modules[url];
if (alreadyLoaded != null) {
var currentConfiguration = configuration ?? _configuration;
if (_moduleConfigurations[url]!.opaqueId !=
currentConfiguration.opaqueId &&
if (!_moduleConfigurations[url]!.sameOriginal(currentConfiguration) &&
currentConfiguration is ExplicitConfiguration) {
var message = namesInErrors
? "${p.prettyUri(url)} was already loaded, so it can't be "
Expand Down Expand Up @@ -2091,7 +2090,7 @@ class _EvaluateVisitor
}

Future<Value?> visitUseRule(UseRule node) async {
var configuration = Configuration.empty();
var configuration = const Configuration.empty();
if (node.configuration.isNotEmpty) {
var values = <String, ConfiguredValue>{};
for (var variable in node.configuration) {
Expand Down
13 changes: 6 additions & 7 deletions lib/src/visitor/evaluate.dart
Expand Up @@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: 9064ba88b38e5cfcc31fd345b185d2c334b490a6
// Checksum: ad5691d0c80b924308f6ee03863fa8c7f5e25ca0
//
// ignore_for_file: unused_import

Expand Down Expand Up @@ -149,7 +149,7 @@ class _EvaluateVisitor
/// All modules that have been loaded and evaluated so far.
final _modules = <Uri, Module<Callable>>{};

/// Configuration seen by a module URI.
/// The first [Configuration] used to load a module [Uri].
final _moduleConfigurations = <Uri, Configuration>{};

/// A map from canonical module URLs to the nodes whose spans indicate where
Expand Down Expand Up @@ -313,7 +313,7 @@ class _EvaluateVisitor
/// The configuration for the current module.
///
/// If this is empty, that indicates that the current module is not configured.
var _configuration = Configuration.empty();
var _configuration = const Configuration.empty();

/// Creates a new visitor.
///
Expand Down Expand Up @@ -475,7 +475,7 @@ class _EvaluateVisitor
var withMap = arguments[1].realNull?.assertMap("with").contents;

var callableNode = _callableNode!;
var configuration = Configuration.empty();
var configuration = const Configuration.empty();
if (withMap != null) {
var values = <String, ConfiguredValue>{};
var span = callableNode.span;
Expand Down Expand Up @@ -678,8 +678,7 @@ class _EvaluateVisitor
var alreadyLoaded = _modules[url];
if (alreadyLoaded != null) {
var currentConfiguration = configuration ?? _configuration;
if (_moduleConfigurations[url]!.opaqueId !=
currentConfiguration.opaqueId &&
if (!_moduleConfigurations[url]!.sameOriginal(currentConfiguration) &&
currentConfiguration is ExplicitConfiguration) {
var message = namesInErrors
? "${p.prettyUri(url)} was already loaded, so it can't be "
Expand Down Expand Up @@ -2083,7 +2082,7 @@ class _EvaluateVisitor
}

Value? visitUseRule(UseRule node) {
var configuration = Configuration.empty();
var configuration = const Configuration.empty();
if (node.configuration.isNotEmpty) {
var values = <String, ConfiguredValue>{};
for (var variable in node.configuration) {
Expand Down
1 change: 0 additions & 1 deletion pubspec.yaml
Expand Up @@ -30,7 +30,6 @@ dependencies:
tuple: ^2.0.0
watcher: ^1.0.0
http: ^0.13.3
uuid: ^3.0.6

dev_dependencies:
analyzer: ^3.0.0
Expand Down

0 comments on commit 7f0330f

Please sign in to comment.