Skip to content

Commit

Permalink
Detached rulesets without scoping. #186
Browse files Browse the repository at this point in the history
  • Loading branch information
jurcovicovam committed Jun 23, 2014
1 parent 6bf9ad3 commit 6d74ad6
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package com.github.sommeri.less4j.core.compiler.expressions;

import com.github.sommeri.less4j.core.compiler.stages.MixinCompilationResult;
import com.github.sommeri.less4j.core.compiler.stages.BodyCompilationResult;
import com.github.sommeri.less4j.utils.ArraysUtils.Filter;

public enum GuardValue {
USE, DO_NOT_USE, USE_IF_DEFAULT, USE_IF_NOT_DEFAULT;

public Filter<MixinCompilationResult> filter() {
public Filter<BodyCompilationResult> filter() {
return new DefaultFunctionUseFilter(this);
}
}

class DefaultFunctionUseFilter implements Filter<MixinCompilationResult> {
class DefaultFunctionUseFilter implements Filter<BodyCompilationResult> {

private final GuardValue value;

Expand All @@ -21,7 +21,7 @@ public DefaultFunctionUseFilter(GuardValue value) {
}

@Override
public boolean accept(MixinCompilationResult t) {
public boolean accept(BodyCompilationResult t) {
return t.getGuardValue().equals(value);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.sommeri.less4j.core.compiler.expressions;

import com.github.sommeri.less4j.core.ast.Expression;
import com.github.sommeri.less4j.core.compiler.scopes.IScope;

@Deprecated //FIXME: !!!!!!!!!!!!!!!! delete interface
public interface LocalScopeFilter {

IScope apply(IScope input);

Expression apply(Expression value);

}
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,8 @@ public static boolean isQuotelessUrlFunction(ASTCssNode kid) {
return "".equals(stringParameter.getQuoteType());
}

public static boolean isExpression(ASTCssNode kid) {
return kid instanceof Expression;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@
import java.util.List;

import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.ReusableStructure;
import com.github.sommeri.less4j.core.compiler.expressions.GuardValue;
import com.github.sommeri.less4j.core.compiler.scopes.IScope;
import com.github.sommeri.less4j.utils.ArraysUtils;

public class MixinCompilationResult {
public class BodyCompilationResult {

private ReusableStructure mixin;
private ASTCssNode compiledBodyOwner;
private List<ASTCssNode> replacement;
private IScope returnValues;
private GuardValue guardValue;

public MixinCompilationResult(ReusableStructure mixin, List<ASTCssNode> replacement, IScope returnValues) {
this.mixin = mixin;
public BodyCompilationResult(ASTCssNode compiledBodyOwner, List<ASTCssNode> replacement, IScope returnValues) {
this.compiledBodyOwner = compiledBodyOwner;
this.replacement = replacement;
this.returnValues = returnValues;
}
Expand Down Expand Up @@ -45,17 +44,17 @@ public void setReturnValues(IScope returnValues) {
this.returnValues = returnValues;
}

public ReusableStructure getMixin() {
return mixin;
public ASTCssNode getCompiledBodyOwner() {
return compiledBodyOwner;
}

public void setMixin(ReusableStructure mixin) {
this.mixin = mixin;
public void setCompiledBodyOwner(ASTCssNode compiledBodyOwner) {
this.compiledBodyOwner = compiledBodyOwner;
}

@Override
protected MixinCompilationResult clone() {
return new MixinCompilationResult(mixin.clone(), ArraysUtils.deeplyClonedList(replacement), returnValues);
protected BodyCompilationResult clone() {
return new BodyCompilationResult(compiledBodyOwner.clone(), ArraysUtils.deeplyClonedList(replacement), returnValues);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.List;
import java.util.Set;

import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.MixinReference;
import com.github.sommeri.less4j.core.ast.ReusableStructure;
import com.github.sommeri.less4j.core.compiler.expressions.GuardValue;
Expand All @@ -21,7 +22,7 @@ public DefaultGuardHelper(ProblemsHandler problemsHandler) {
this.problemsHandler = problemsHandler;
}

public List<MixinCompilationResult> chooseMixinsToBeUsed(List<MixinCompilationResult> compiledMixins, final MixinReference reference) {
public List<BodyCompilationResult> chooseMixinsToBeUsed(List<BodyCompilationResult> compiledMixins, final MixinReference reference) {
// count how many mixins of each kind we encountered
int normalMixinsCnt = ArraysUtils.count(compiledMixins, GuardValue.USE.filter());
int ifNotCnt = ArraysUtils.count(compiledMixins, GuardValue.USE_IF_NOT_DEFAULT.filter());
Expand All @@ -38,7 +39,7 @@ public List<MixinCompilationResult> chooseMixinsToBeUsed(List<MixinCompilationRe

//there are multiple mixins using default() function and nothing else - that is ambiguous (period).
if (ifDefaultCnt+ifNotCnt > 1) {
List<MixinCompilationResult> errorSet = keepOnly(compiledMixins, GuardValue.USE_IF_DEFAULT,GuardValue.USE_IF_NOT_DEFAULT);
List<BodyCompilationResult> errorSet = keepOnly(compiledMixins, GuardValue.USE_IF_DEFAULT,GuardValue.USE_IF_NOT_DEFAULT);
problemsHandler.ambiguousDefaultSet(reference, extractOriginalMixins(errorSet));
//no mixins are going to be used
return Collections.emptyList();
Expand All @@ -56,22 +57,22 @@ public List<MixinCompilationResult> chooseMixinsToBeUsed(List<MixinCompilationRe
* @param kind - types of mixins that are going to stay.
* @return compiledMixins - for convenience
*/
private List<MixinCompilationResult> keepOnly(List<MixinCompilationResult> compiledMixins, GuardValue... kind) {
private List<BodyCompilationResult> keepOnly(List<BodyCompilationResult> compiledMixins, GuardValue... kind) {
Set<GuardValue> expectedUses = ArraysUtils.asSet(kind);
Iterator<MixinCompilationResult> iterator = compiledMixins.iterator();
Iterator<BodyCompilationResult> iterator = compiledMixins.iterator();
while (iterator.hasNext()) {
MixinCompilationResult compiled = iterator.next();
BodyCompilationResult compiled = iterator.next();
if (!expectedUses.contains(compiled.getGuardValue())) {
iterator.remove();
}
}
return compiledMixins;
}

private List<ReusableStructure> extractOriginalMixins(List<MixinCompilationResult> compiledMixins) {
List<ReusableStructure> result = new ArrayList<ReusableStructure>();
for (MixinCompilationResult compiled : compiledMixins) {
result.add(compiled.getMixin());
private List<ASTCssNode> extractOriginalMixins(List<BodyCompilationResult> compiledMixins) {
List<ASTCssNode> result = new ArrayList<ASTCssNode>();
for (BodyCompilationResult compiled : compiledMixins) {
result.add(compiled.getCompiledBodyOwner());
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.ASTCssNodeType;
import com.github.sommeri.less4j.core.ast.DetachedRuleset;
import com.github.sommeri.less4j.core.ast.Expression;
import com.github.sommeri.less4j.core.ast.ReusableStructure;
import com.github.sommeri.less4j.core.ast.RuleSet;
import com.github.sommeri.less4j.core.ast.VariableDeclaration;
Expand Down Expand Up @@ -50,7 +52,7 @@ private IScope buildScope(ASTCssNode node) {
buildScope(kid);

if (kid.getType() == ASTCssNodeType.IMPORT) {
importsPlaceholders.add(createPlaceholderScope(kid));
importsPlaceholders.add(createPlaceholderScope(kid));
} else if (kid.getType() == ASTCssNodeType.VARIABLE_DECLARATION) {
currentScope.registerVariable((VariableDeclaration) kid);
manipulator.removeFromBody(kid);
Expand All @@ -62,6 +64,13 @@ private IScope buildScope(ASTCssNode node) {
if (bodyScope.hasParent())
bodyScope.getParent().removedFromAst(); // remove also arguments scope from tree
manipulator.removeFromBody(kid);
} else if (kid.getType() == ASTCssNodeType.DETACHED_RULESET) {
DetachedRuleset detached = (DetachedRuleset) kid;
IScope bodyScope = currentScope.childByOwners(detached, detached.getBody());
if (bodyScope.hasParent())
bodyScope.getParent().removedFromAst(); // remove also arguments scope from tree
bodyScope.removedFromAst();
detached.setScope(bodyScope);
} else if (kid.getType() == ASTCssNodeType.RULE_SET) {
RuleSet ruleSet = (RuleSet) kid;
if (ruleSet.isUsableAsReusableStructure()) {
Expand All @@ -70,6 +79,11 @@ private IScope buildScope(ASTCssNode node) {
}
} else if (kid.getType() == ASTCssNodeType.MIXIN_REFERENCE) {
currentScope.createDataPlaceholder();
} else if (kid.getType() == ASTCssNodeType.DETACHED_RULESET_REFERENCE) {
currentScope.createDataPlaceholder();
} else if (AstLogic.isExpression(kid)) {
Expression value = (Expression) kid;
value.setScope(currentScope);
}
}

Expand Down Expand Up @@ -105,7 +119,7 @@ private void decreaseScope() {
private void increaseScope(ASTCssNode owner) {
if (currentScope == null) {
currentScope = ScopeFactory.createDefaultScope(owner);
} else if(AstLogic.isBodyOwner(owner)) {
} else if (AstLogic.isBodyOwner(owner)) {
currentScope = ScopeFactory.createBodyOwnerScope(owner, currentScope);
} else {
currentScope = ScopeFactory.createScope(owner, currentScope);
Expand All @@ -118,7 +132,7 @@ private void increaseScope(ASTCssNode owner) {
private PlaceholderScope createPlaceholderScope(ASTCssNode owner) {
if (currentScope == null) {
throw new BugHappened("No parent scope available.", owner);
}
}

return ScopeFactory.createPlaceholderScope(owner, currentScope);
}
Expand Down
Loading

0 comments on commit 6d74ad6

Please sign in to comment.