diff --git a/src/main/java/com/github/sommeri/less4j/core/ast/ASTCssNode.java b/src/main/java/com/github/sommeri/less4j/core/ast/ASTCssNode.java index 655719ff..32e14263 100644 --- a/src/main/java/com/github/sommeri/less4j/core/ast/ASTCssNode.java +++ b/src/main/java/com/github/sommeri/less4j/core/ast/ASTCssNode.java @@ -146,4 +146,14 @@ public void configureParentToAllChilds() { } } + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()).append(" ("); + builder.append(getSourceLine()).append(":").append(getSourceColumn()); + builder.append(")"); + + return builder.toString(); + } + } diff --git a/src/main/java/com/github/sommeri/less4j/core/ast/DetachedRulesetReference.java b/src/main/java/com/github/sommeri/less4j/core/ast/DetachedRulesetReference.java index bbebde08..76f0d077 100644 --- a/src/main/java/com/github/sommeri/less4j/core/ast/DetachedRulesetReference.java +++ b/src/main/java/com/github/sommeri/less4j/core/ast/DetachedRulesetReference.java @@ -12,6 +12,7 @@ public class DetachedRulesetReference extends ASTCssNode { public DetachedRulesetReference(HiddenTokenAwareTree token, Variable variable) { super(token); + this.variable = variable; } public Variable getVariable() { diff --git a/src/main/java/com/github/sommeri/less4j/core/ast/Expression.java b/src/main/java/com/github/sommeri/less4j/core/ast/Expression.java index 3816c48f..39720fb7 100644 --- a/src/main/java/com/github/sommeri/less4j/core/ast/Expression.java +++ b/src/main/java/com/github/sommeri/less4j/core/ast/Expression.java @@ -3,14 +3,36 @@ import java.util.Collections; import java.util.List; +import com.github.sommeri.less4j.core.ast.annotations.NotAstProperty; +import com.github.sommeri.less4j.core.compiler.scopes.IScope; import com.github.sommeri.less4j.core.parser.HiddenTokenAwareTree; -public abstract class Expression extends ASTCssNode { +public abstract class Expression extends ASTCssNode implements IScopeAware { + + private IScope ownerScope; public Expression(HiddenTokenAwareTree token) { super(token); } + @Override + @NotAstProperty + public IScope getScope() { + return ownerScope; + } + + @Override + @NotAstProperty + public void setScope(IScope scope) { + this.ownerScope = scope; + } + + @Override + @NotAstProperty + public boolean hasScope() { + return ownerScope!=null; + } + public List splitByComma() { return Collections.singletonList(this); } diff --git a/src/main/java/com/github/sommeri/less4j/core/ast/IScopeAware.java b/src/main/java/com/github/sommeri/less4j/core/ast/IScopeAware.java new file mode 100644 index 00000000..b447da1e --- /dev/null +++ b/src/main/java/com/github/sommeri/less4j/core/ast/IScopeAware.java @@ -0,0 +1,24 @@ +package com.github.sommeri.less4j.core.ast; + +import com.github.sommeri.less4j.core.ast.annotations.NotAstProperty; +import com.github.sommeri.less4j.core.compiler.scopes.IScope; + +/** + * Contains scope associated with the node. It would be much more cleaner if + * the solution would keep ast completely independent from scope. That being said, + * I did not found such clean solution that would not be also fragile or too + * complicated or required too much boiler plate like code. + * + */ +public interface IScopeAware { + + @NotAstProperty + IScope getScope(); + + @NotAstProperty + void setScope(IScope scope); + + @NotAstProperty + boolean hasScope(); + +} diff --git a/src/main/java/com/github/sommeri/less4j/core/ast/ListExpression.java b/src/main/java/com/github/sommeri/less4j/core/ast/ListExpression.java index 909085b5..2443cbd4 100644 --- a/src/main/java/com/github/sommeri/less4j/core/ast/ListExpression.java +++ b/src/main/java/com/github/sommeri/less4j/core/ast/ListExpression.java @@ -6,6 +6,7 @@ import com.github.sommeri.less4j.core.ast.ListExpressionOperator.Operator; import com.github.sommeri.less4j.core.ast.annotations.NotAstProperty; +import com.github.sommeri.less4j.core.compiler.scopes.IScope; import com.github.sommeri.less4j.core.parser.HiddenTokenAwareTree; import com.github.sommeri.less4j.utils.ArraysUtils; @@ -20,6 +21,11 @@ public ListExpression(HiddenTokenAwareTree token, List expressions, this.operator = operator; } + public ListExpression(HiddenTokenAwareTree token, List expressions, ListExpressionOperator operator, IScope scope) { + this(token, expressions, operator); + setScope(scope); + } + public ListExpressionOperator getOperator() { return operator; } diff --git a/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/BasicScope.java b/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/BasicScope.java index 595c7865..f0986926 100644 --- a/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/BasicScope.java +++ b/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/BasicScope.java @@ -20,13 +20,13 @@ public IScope firstChild() { 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; } @@ -62,7 +62,6 @@ public boolean seesLocalDataOf(IScope otherScope) { return getParent().seesLocalDataOf(otherScope); } - public IScope getRootScope() { if (!hasParent()) return this; @@ -119,7 +118,13 @@ public String toFullName() { private String toSimpleName() { List names = getNames(); - return "" + getType() + names; + if (names!=null && !names.isEmpty()) + return getType() + names; + + if (ScopeFactory.DEFAULT!=getType()) + return getType() + "[" + getOwner().toString() + "]"; + + return getType(); } public String toLongString() { diff --git a/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/IteratedScope.java b/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/IteratedScope.java index e622fd2f..baeefbb9 100644 --- a/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/IteratedScope.java +++ b/src/main/java/com/github/sommeri/less4j/core/compiler/scopes/IteratedScope.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Iterator; +import com.github.sommeri.less4j.core.problems.BugHappened; public class IteratedScope { @@ -24,6 +25,8 @@ public IteratedScope getNextChild() { do { if (childsIterator.hasNext()) child = childsIterator.next(); + else + throw new BugHappened("Child scope was expected but missing", getScope().getOwner()); } while (!child.isPresentInAst()); return new IteratedScope(child);