All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.squarespace.less.model.Mixin Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2014 SQUARESPACE, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.squarespace.less.model;

import static com.squarespace.less.core.LessUtils.safeEquals;

import com.squarespace.less.core.Buffer;
import com.squarespace.less.exec.ExecEnv;


/**
 * 

* A Mixin is a macro that has a few function-like properties. When a mixin * is called, the mixin is expanded into the calling scope. *

* *

* A mixin is not a proper function, as the mixin body's local scope is * intermingled with the caller's, so it can see variables in the caller's scope. *

* *

* The values of local variables depend heavily on the order of evaluation * inside the mixin body and can lead to confusing outcomes. *

*/ public class Mixin extends BlockNode { /** * Name of the mixin. */ protected final String name; /** * Mixin's parameters. */ protected final MixinParams params; /** * Mixin's optional guard expression. */ protected final Guard guard; /** * Closure attached to this mixin definition. */ protected ExecEnv closure; /** * Number of times this mixin's body has been evaluated. Used to detect * and limit recursion. */ protected int entryCount; /** * Constructs a mixin with the given name, parameters and guard expression. */ public Mixin(String name, MixinParams params, Guard guard) { this(name, params, guard, new Block()); } /** * Constructs a mixin with the given name, parameters and guard expression, * with the given block. */ public Mixin(String name, MixinParams params, Guard guard, Block block) { super(block); this.name = name; this.params = params; this.guard = guard; } /** * Creates a copy of this mixin. */ public Mixin copy() { Mixin result = new Mixin(name, params, guard, block.copy()); result.copyStructure(this); result.closure = closure; if (originalBlockNode != null) { result.originalBlockNode = originalBlockNode; } return result; } /** * Returns the mixin's name. */ public String name() { return name; } /** * Returns the mixin's parameters. */ public MixinParams params() { return params; } /** * Returns the mixin's guard expression. */ public Guard guard() { return guard; } /** * Returns the number of times this mixin's body has been evaluated. */ public int entryCount() { return entryCount; } /** * Begins evaluating the mixin's body. */ public void enter() { entryCount++; } /** * Ends evaluating the mixin's body. */ public void exit() { entryCount--; } /** * Returns the closure environment attached to the mixin's definition. */ public ExecEnv closure() { return closure; } /** * Sets the closure on this mixin definition. */ public void closure(ExecEnv env) { this.closure = env.copy(); } /** * See {@link Node#type()} */ @Override public NodeType type() { return NodeType.MIXIN; } /** * See {@link Node#repr(Buffer)} */ @Override public void repr(Buffer buf) { buf.append(name).append('('); if (params != null) { params.repr(buf); } buf.append(')'); if (guard != null) { buf.append(" when "); guard.repr(buf); } if (buf.compress()) { buf.append('{'); } else { buf.append(" {\n"); } buf.incrIndent(); block.repr(buf); buf.decrIndent(); if (buf.compress()) { buf.append('}'); } else { buf.indent().append("}\n"); } } /** * See {@link Node#modelRepr(Buffer)} */ @Override public void modelRepr(Buffer buf) { typeRepr(buf); posRepr(buf); buf.append(' ').append(name).append('\n'); buf.incrIndent(); if (params != null) { buf.indent(); params.modelRepr(buf); buf.append('\n'); } if (guard != null) { buf.indent(); guard.modelRepr(buf); buf.append('\n'); } buf.indent(); super.modelRepr(buf); buf.decrIndent().append('\n'); } @Override public boolean equals(Object obj) { if (obj instanceof Mixin) { Mixin other = (Mixin)obj; return safeEquals(name, other.name) && safeEquals(params, other.params) && safeEquals(guard, other.guard); } return false; } @Override public String toString() { return ModelUtils.toString(this); } @Override public int hashCode() { return ModelUtils.notHashable(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy