content: // Copyright 2016 Google Inc. Use of this source code is governed by an
  // 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 '../../../exception.dart';
  import '../../../parse/scss.dart';
  import '../../../utils.dart';
  import '../../../util/span.dart';
  import '../../../visitor/interface/statement.dart';
  import '../expression.dart';
  import '../declaration.dart';
  import '../statement.dart';
  import 'silent_comment.dart';
  
  /// A variable declaration.
  ///
  /// This defines or sets a variable.
  ///
  /// {@category AST}
  final class VariableDeclaration extends Statement implements SassDeclaration {
    /// The namespace of the variable being set, or `null` if it's defined or set
    /// without a namespace.
    final String? namespace;
  
    /// The name of the variable, with underscores converted to hyphens.
    final String name;
  
    /// The comment immediately preceding this declaration.
    SilentComment? comment;
  
    /// The value the variable is being assigned to.
    final Expression expression;
  
    /// Whether this is a guarded assignment.
    ///
    /// Guarded assignments only happen if the variable is undefined or `null`.
    final bool isGuarded;
  
    /// Whether this is a global assignment.
    ///
    /// Global assignments always affect only the global scope.
    final bool isGlobal;
  
    final FileSpan span;
  
    /// The variable name as written in the document, without underscores
    /// converted to hyphens and including the leading `$`.
    ///
    /// This isn't particularly efficient, and should only be used for error
    /// messages.
    String get originalName => declarationName(span);
  
    FileSpan get nameSpan {
      var span = this.span;
      if (namespace != null) span = span.withoutNamespace();
      return span.initialIdentifier(includeLeading: 1);
    }
  
    FileSpan? get namespaceSpan =>
        namespace == null ? null : span.initialIdentifier();
  
    VariableDeclaration(
      this.name,
      this.expression,
      this.span, {
      this.namespace,
      bool guarded = false,
      bool global = false,
      this.comment,
    })  : isGuarded = guarded,
          isGlobal = global {
      if (namespace != null && global) {
        throw ArgumentError(
          "Other modules' members can't be defined with !global.",
        );
      }
    }
  
    /// Parses a variable declaration from [contents].
    ///
    /// If passed, [url] is the name of the file from which [contents] comes.
    ///
    /// Throws a [SassFormatException] if parsing fails.
    ///
    /// @nodoc
    @internal
    factory VariableDeclaration.parse(String contents, {Object? url}) =>
        ScssParser(contents, url: url).parseVariableDeclaration().$1;
  
    T accept<T>(StatementVisitor<T> visitor) =>
        visitor.visitVariableDeclaration(this);
  
    String toString() {
      var buffer = StringBuffer();
      if (namespace != null) buffer.write("$namespace.");
      buffer.write("\$$name: $expression;");
      return buffer.toString();
    }
  }
  