package com.github.sommeri.less4j.core.compiler.stages;
import java.util.ArrayList;
import java.util.List;
import com.github.sommeri.less4j.core.compiler.scopes.FullMixinDefinition;
import com.github.sommeri.less4j.core.compiler.scopes.IScope;
import com.github.sommeri.less4j.core.compiler.scopes.ScopeFactory;
import com.github.sommeri.less4j.core.compiler.scopes.view.ScopeView;
public class CallerCalleeScopeJoiner {
public ScopeView joinIfIndependentAndPreserveContent(IScope callerScope, IScope bodyScope) {
ScopeView result = joinIfIndependent(callerScope, bodyScope);
result.toIndependentWorkingCopyAllParents();
return result;
}
public ScopeView joinIfIndependent(IScope callerScope, IScope bodyScope) {
// locally defined mixin does not require any other action
boolean isLocallyDefined = isLocallyDefined(callerScope, bodyScope);
if (isLocallyDefined) {
return ScopeFactory.createSaveableView(bodyScope);
}
//join scopes
ScopeView result = ScopeFactory.createJoinedScopesView(callerScope, bodyScope);
return result;
}
private boolean isLocallyDefined(IScope callerScope, IScope bodyScope) {
boolean isLocallyDefined = true;
IScope checkScope = callerScope;
while (isLocallyDefined && checkScope!=null) {
isLocallyDefined = bodyScope.seesLocalDataOf(checkScope);
checkScope = checkScope.getParent();
}
return isLocallyDefined;
}
public List<FullMixinDefinition> mixinsToImport(IScope callerScope, IScope calleeScope, List<FullMixinDefinition> unmodifiedMixinsToImport) {
List<FullMixinDefinition> result = new ArrayList<FullMixinDefinition>();
for (FullMixinDefinition mixinToImport : unmodifiedMixinsToImport) {
boolean isLocalImport = isLocallyDefined(calleeScope, mixinToImport.getScope());//why caller and not callee???
ScopeView newScope = null;
if (isLocalImport) {
// we need to copy the whole tree, because this runs inside referenced mixin scope
// snapshot and imported mixin needs to remember the scope as it is now
newScope = ScopeFactory.createSaveableView(mixinToImport.getScope());
} else {
// since this is non-local import, we need to join reference scope and imported mixins scope
// imported mixin needs to have access to variables defined in caller
newScope = ScopeFactory.createJoinedScopesView(calleeScope, mixinToImport.getScope());
}
newScope.toIndependentWorkingCopyAllParents();
result.add(new FullMixinDefinition(mixinToImport.getMixin(), newScope));
}
return result;
}
}