package scotch.compiler.syntax.scope;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertThat;
import static org.junit.rules.ExpectedException.none;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static scotch.compiler.syntax.scope.Scope.scope;
import static scotch.util.TestUtil.intType;
import static scotch.symbol.Symbol.symbol;
import static scotch.symbol.Symbol.unqualified;
import static scotch.compiler.syntax.type.Types.t;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import scotch.symbol.SymbolResolver;
import scotch.compiler.syntax.type.DefaultTypeScope;
import scotch.compiler.syntax.util.DefaultSymbolGenerator;
import scotch.compiler.syntax.util.SymbolGenerator;
@RunWith(MockitoJUnitRunner.class)
public class ChildScopeTest {
@Rule
public final ExpectedException exception = none();
@Mock
private Scope parentScope;
private Scope childScope;
@Before
public void setUp() {
when(parentScope.reserveType()).thenReturn(t(20));
SymbolResolver symbolResolver = mock(SymbolResolver.class);
SymbolGenerator symbolGenerator = new DefaultSymbolGenerator();
childScope = scope(parentScope, new DefaultTypeScope(symbolGenerator, symbolResolver), symbolResolver, symbolGenerator, "scotch.test");
}
@Test
public void leavingScopeShouldGiveParent() {
assertThat(childScope.leaveScope(), sameInstance(parentScope));
assertThat(childScope.enterScope().leaveScope(), sameInstance(childScope));
}
@Test
public void shouldDelegateToParentWhenQualifyingSymbolThisIsNotDefinedLocally() {
childScope.qualify(unqualified("fn"));
verify(parentScope).qualify(unqualified("fn"));
}
@Test
public void shouldNotDelegateToParentWhenValueDefined() {
childScope.defineValue(unqualified("x"), t(2));
childScope.getValue(unqualified("x"));
verify(parentScope, never()).getValue(unqualified("x"));
}
@Test
public void shouldGetContextFromParent() {
when(parentScope.getContext(intType())).thenReturn(ImmutableSet.of(symbol("scotch.data.num.Num")));
assertThat(childScope.getContext(intType()), contains(
symbol("scotch.data.num.Num")
));
}
}