com.google.common.css.compiler.ast.CssNodesListNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of closure-stylesheets Show documentation
Show all versions of closure-stylesheets Show documentation
Closure Stylesheets is an extension to CSS that adds variables,
functions,
conditionals, and mixins to standard CSS. The tool also supports
minification, linting, RTL flipping, and CSS class renaming.
/*
* Copyright 2008 Google 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.google.common.css.compiler.ast;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nullable;
/**
* Represents a list of nodes. This is meant to represent a succession of
* statements that logically group together as one node in the tree. Examples
* include:
*
* - all the statements in a stylesheet, except for the ones that can only
* appear on top ({@code charset}, {@code import}, etc.)
*
- all the declarations inside a ruleset, a font face or a page rule
*
- all the nodes that form a chain of if-elseif-else rules
*
- the block that belongs to some of the at rules, such as {@code media}
*
*
* @param the list is restricted to nodes of this type
*/
public abstract class CssNodesListNode extends CssNode {
protected List children = Lists.newArrayList();
private final boolean isEnclosedWithBraces;
/**
* Constructor of a list of nodes alike.
*
* @param isEnclosedWithBraces
*/
public CssNodesListNode(boolean isEnclosedWithBraces) {
this(isEnclosedWithBraces, null);
}
/**
* Constructor of a list of nodes alike.
*
* @param isEnclosedWithBraces
* @param comments
*/
public CssNodesListNode(boolean isEnclosedWithBraces,
@Nullable List comments) {
super(null, comments, null);
this.isEnclosedWithBraces = isEnclosedWithBraces;
}
/**
* Constructor of a list of nodes alike.
*
* @param isEnclosedWithBraces
* @param comments
* @param childrenList list of children
*/
public CssNodesListNode(boolean isEnclosedWithBraces,
List childrenList,
@Nullable List comments) {
super(null, comments, null);
for (T child : childrenList) {
@SuppressWarnings("unchecked")
T childCopy = (T) child.deepCopy();
addChildToBack(childCopy);
}
this.isEnclosedWithBraces = isEnclosedWithBraces;
}
/**
* Copy constructor.
*
* @param node
*/
public CssNodesListNode(CssNodesListNode extends CssNode> node) {
super(
node.getParent(),
node.getComments(),
node.getSourceCodeLocation());
this.isEnclosedWithBraces = node.isEnclosedWithBraces;
for (CssNode child : node.childIterable()) {
@SuppressWarnings("unchecked")
T childCopy = (T) child.deepCopy();
addChildToBack(childCopy);
}
}
public List getChildren() {
return Collections.unmodifiableList(children);
}
public Iterator getChildIterator() {
return children.iterator();
}
public Iterable childIterable() {
return Iterables.unmodifiableIterable(children);
}
void setChildren(List children) {
Preconditions.checkArgument(!children.contains(null));
removeAsParentOfNodes(this.children);
this.children = copyToList(children);
becomeParentForNodes(this.children);
}
T removeChildAt(int index) {
Preconditions.checkState(index >= 0 && index < children.size());
T child = children.get(index);
removeAsParentOfNode(child);
children.remove(index);
return child;
}
// TODO(dgajda): Make it package private once we can walk the tree backwards
// and ReplaceConstantReferences won't need to use this method directly.
public void replaceChildAt(int index, List extends T> newChildren) {
Preconditions.checkState(index >= 0 && index < children.size());
Preconditions.checkArgument(!newChildren.contains(null));
removeChildAt(index);
children.addAll(index, newChildren);
becomeParentForNodes(newChildren);
}
public T getChildAt(int index) {
Preconditions.checkState(index >= 0 && index < children.size());
return children.get(index);
}
public int numChildren() {
return children.size();
}
T removeLastChild() {
return removeChildAt(children.size() - 1);
}
public T getLastChild() {
return children.get(children.size() - 1);
}
public void addChildToBack(T child) {
Preconditions.checkNotNull(child);
this.children.add(child);
becomeParentForNode(child);
}
public boolean isEmpty() {
return children.isEmpty();
}
public boolean isEnclosedWithBraces() {
return isEnclosedWithBraces;
}
/**
* For debugging only.
*/
@Override
public String toString() {
StringBuffer output = new StringBuffer();
if (!getComments().isEmpty()) {
output.append("[");
output.append(getComments().toString());
output.append(children.toString());
output.append("]");
} else {
output.append(children.toString());
}
return output.toString();
}
}