/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2015, MontiCore, All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* ******************************************************************************
*/
package de.monticore.symboltable;
import de.monticore.io.paths.ModelPath;
import de.monticore.symboltable.mocks.languages.entity.EntitySymbol;
import de.monticore.symboltable.resolving.CommonResolvingFilter;
import de.monticore.symboltable.resolving.ResolvedSeveralEntriesException;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Pedram Mir Seyed Nazari
*/
public class ArtifactScopeTest {
@Test
public void testArtifactScopeWithoutImportStatements() {
final CommonResolvingFilter<EntitySymbol> classResolver = new CommonResolvingFilter<>(EntitySymbol.KIND);
final MutableScope globalScope = new GlobalScope(new ModelPath(), new LinkedHashSet<>(), new ResolvingConfiguration());
globalScope.addResolver(classResolver);
ArtifactScope artifactScope1 = new ArtifactScope(Optional.of(globalScope), "p", new ArrayList<>());
artifactScope1.addResolver(classResolver);
EntitySymbol classA = new EntitySymbol("A");
artifactScope1.add(classA);
Scope classAScope = classA.getSpannedScope();
ArtifactScope artifactScope2 = new ArtifactScope(Optional.of(globalScope), "q", new ArrayList<>());
artifactScope2.addResolver(classResolver);
EntitySymbol classQB = new EntitySymbol("B");
artifactScope2.add(classQB);
// resolve by qualified name
assertSame(classQB, classAScope.resolve("q.B", EntitySymbol.KIND).get());
// no imports defined, hence, resolving by simple name fails
assertNull(classAScope.resolve("B", EntitySymbol.KIND).orElse(null));
ArtifactScope artifactScope3 = new ArtifactScope(Optional.of(globalScope), "r", new ArrayList<>());
artifactScope3.addResolver(classResolver);
EntitySymbol classRB = new EntitySymbol("B");
artifactScope3.add(classRB);
// Now, besides q.B the symbol r.B is defines in the global scope (resp. in the compilation scopes)
// => Nothing changes
// resolve by qualified name
assertSame(classQB, classAScope.resolve("q.B", EntitySymbol.KIND).get());
// no imports defined, hence, resolving by simple name fails
assertNull(classAScope.resolve("B", EntitySymbol.KIND).orElse(null));
}
@Test
public void testArtifactScopeWithImportStatements() {
final CommonResolvingFilter<EntitySymbol> classResolver = new CommonResolvingFilter<>(EntitySymbol.KIND);
final MutableScope globalScope = new GlobalScope(new ModelPath(), new LinkedHashSet<>(), new ResolvingConfiguration());
globalScope.addResolver(classResolver);
ArtifactScope artifactScope1 = new ArtifactScope(Optional.of(globalScope), "p", Arrays.asList(
new ImportStatement("q", true), new ImportStatement("r.B", false)));
artifactScope1.addResolver(classResolver);
EntitySymbol classA = new EntitySymbol("A");
artifactScope1.add(classA);
MutableScope classAScope = classA.getMutableSpannedScope();
classAScope.addResolver(classResolver);
ArtifactScope artifactScope2 = new ArtifactScope(Optional.of(globalScope), "q", new ArrayList<>());
artifactScope2.addResolver(classResolver);
EntitySymbol classQB = new EntitySymbol("B");
classQB.getMutableSpannedScope().addResolver(classResolver);
artifactScope2.add(classQB);
// resolve by qualified name
assertSame(classQB, classAScope.resolve("q.B", EntitySymbol.KIND).get());
// q.B is imported, hence, resolving by simple succeeds.
assertSame(classQB, classAScope.resolve("B", EntitySymbol.KIND).orElse(null));
ArtifactScope artifactScope3 = new ArtifactScope(Optional.of(globalScope), "r", new ArrayList<>());
artifactScope3.addResolver(classResolver);
EntitySymbol classRB = new EntitySymbol("B");
classRB.getMutableSpannedScope().addResolver(classResolver);
artifactScope3.add(classRB);
// Now, besides q.B the symbol r.B is defined in the global scope
// (resp. in the artifact scope scopes)
// resolve by qualified name
assertSame(classQB, classAScope.resolve("q.B", EntitySymbol.KIND).get());
// resolve by simple name
try {
classAScope.resolve("B", EntitySymbol.KIND);
fail();
}
catch (ResolvedSeveralEntriesException e) {
assertEquals(2, e.getSymbols().size());
assertTrue(e.getSymbols().contains(classQB));
assertTrue(e.getSymbols().contains(classRB));
}
}
@Test
public void testResolveUnqualifiedSymbolInSamePackage() {
final CommonResolvingFilter<EntitySymbol> classResolver = new CommonResolvingFilter<>(EntitySymbol.KIND);
final MutableScope globalScope = new GlobalScope(new ModelPath(), new LinkedHashSet<>(), new ResolvingConfiguration());
globalScope.addResolver(classResolver);
ArtifactScope artifactScope1 = new ArtifactScope(Optional.of(globalScope), "p", new ArrayList<>());
artifactScope1.addResolver(classResolver);
EntitySymbol classA = new EntitySymbol("A");
artifactScope1.add(classA);
Scope classAScope = classA.getSpannedScope();
ArtifactScope artifactScope2 = new ArtifactScope(Optional.of(globalScope), "p", new ArrayList<>());
artifactScope2.addResolver(classResolver);
EntitySymbol classB = new EntitySymbol("B");
artifactScope2.add(classB);
// resolve B with unqualified name, because it is in the same package as A.
assertSame(classB, classAScope.resolve("B", EntitySymbol.KIND).get());
assertSame(classA, classAScope.resolve("A", EntitySymbol.KIND).get());
}
@Test
public void testPackageNameMustBePrefixOfQualifiedSymbolName() {
final CommonResolvingFilter<EntitySymbol> classResolver = new CommonResolvingFilter<>(EntitySymbol.KIND);
final MutableScope globalScope = new GlobalScope(new ModelPath(), new LinkedHashSet<>(), new ResolvingConfiguration());
globalScope.addResolver(classResolver);
ArtifactScope artifactScope1 = new ArtifactScope(Optional.of(globalScope), "p", new ArrayList<>());
artifactScope1.addResolver(classResolver);
EntitySymbol classA = new EntitySymbol("A");
artifactScope1.add(classA);
ArtifactScope artifactScope2 = new ArtifactScope(Optional.of(globalScope), "p2", new ArrayList<>());
artifactScope2.addResolver(classResolver);
EntitySymbol classA2 = new EntitySymbol("A");
artifactScope2.add(classA2);
assertSame(classA, globalScope.resolve("p.A", EntitySymbol.KIND).get());
assertSame(classA2, globalScope.resolve("p2.A", EntitySymbol.KIND).get());
assertNotSame(classA, classA2);
}
@Test
public void testResolveInDefaultPackage() {
final CommonResolvingFilter<EntitySymbol> classResolver = new CommonResolvingFilter<>(EntitySymbol.KIND);
final MutableScope globalScope = new GlobalScope(new ModelPath(), new LinkedHashSet<>(), new ResolvingConfiguration());
globalScope.addResolver(classResolver);
ArtifactScope artifactScope1 = new ArtifactScope(Optional.of(globalScope), "", new ArrayList<>());
artifactScope1.addResolver(classResolver);
EntitySymbol classA = new EntitySymbol("A");
artifactScope1.add(classA);
final Optional<EntitySymbol> entityA = globalScope.resolve("A", EntitySymbol.KIND);
assertTrue(entityA.isPresent());
}
}