package com.github.sommeri.less4j.core.compiler.scopes;
import java.util.Iterator;
import java.util.List;
import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.Expression;
import com.github.sommeri.less4j.core.ast.Variable;
public class BasicScope extends ComposedDumbScope implements IScope {
public BasicScope(ILocalScope localScope, IScopesTree surroundingScopes) {
super(localScope, surroundingScopes);
}
public IScope firstChild() {
return getChilds().get(0);
}
public Expression getValue(Variable variable) {
return getValue(variable.getName());
}
public Expression getValue(String name) {
Expression value = getLocalValue(name);
if (value == null && hasParent()) {
value = getParent().getValue(name);
}
return value;
}
public IScope childByOwners(ASTCssNode headNode, ASTCssNode... restNodes) {
IScope head = getChildOwnerOf(headNode);
if (head == null)
return null;
for (ASTCssNode node : restNodes) {
head = head.getChildOwnerOf(node);
if (head == null)
return null;
}
return head;
}
public IScope getChildOwnerOf(ASTCssNode body) {
for (IScope kid : getChilds()) {
if (kid.getOwner() == body)
return kid;
}
return null;
}
public boolean seesLocalDataOf(IScope otherScope) {
if (getLocalScope().hasTheSameLocalData(otherScope.getLocalScope()))
return true;
if (!hasParent())
return false;
return getParent().seesLocalDataOf(otherScope);
}
// this method might be wasteful, we are looking for the same tree, so there should
// be no need to restart search from top for each parent
public boolean seesAllDataOf(IScope otherScope) {
boolean isLocalImport = seesLocalDataOf(otherScope);
IScope parent = otherScope.getParent();
while (isLocalImport && parent != null) {
isLocalImport = seesLocalDataOf(parent);
parent = parent.getParent();
}
return isLocalImport;
}
public IScope getRootScope() {
if (!hasParent())
return this;
return getParent().getRootScope();
}
public IScope skipBodyOwner() {
if (isBodyOwnerScope())
return firstChild().skipBodyOwner();
return this;
}
public void setParentKeepConsistency(IScope parent) {
if (getSurroundingScopes().hasParent()) {
getParent().getChilds().remove(this);
}
setParent(parent);
if (parent != null)
parent.addChild(this);
}
@Override
public void setParent(IScope parent) {
getSurroundingScopes().setParent(parent);
}
public void replaceChild(IScope parent, IScope child, List<IScope> replacements) {
List<IScope> inList = parent.getChilds();
int indexOf = inList.indexOf(child);
inList.remove(indexOf);
inList.addAll(indexOf, replacements);
for (IScope kid : replacements) {
kid.setParent(parent);
}
}
@Override
public String toString() {
StringBuilder result = new StringBuilder(toFullName());
return result.toString();
}
public String toFullName() {
if (hasParent())
return getParent().toFullName() + " > " + toSimpleName();
return toSimpleName().toString();
}
private String toSimpleName() {
List<String> names = getNames();
if (names!=null && !names.isEmpty())
return getType() + names;
if (ScopeFactory.DEFAULT!=getType())
return getType() + "[" + getOwner().toString() + "]";
return getType();
}
public String toLongString() {
return toLongString(0).toString();
}
public StringBuilder toLongString(int level) {
String prefix = "";
for (int i = 0; i < level; i++) {
prefix += " ";
}
StringBuilder text = new StringBuilder(prefix);
Iterator<String> iNames = getNames().iterator();
text.append(iNames.next());
while (iNames.hasNext()) {
text.append(", ").append(iNames.next());
}
text.append("(").append(getLocalVariables().size()).append(", ").append(getLocalMixins().size());
text.append(") {").append("\n");
for (IScope kid : getChilds()) {
text.append(kid.toLongString(level + 1));
}
text.append(prefix).append("}").append("\n");
return text;
}
}