/*
* Copyright 2003-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.generator.impl.plan;
import jetbrains.mps.generator.impl.RuleUtil;
import jetbrains.mps.generator.impl.interpreted.TemplateMappingConfigurationInterpreted;
import jetbrains.mps.generator.impl.plan.PriorityConflicts.Kind;
import jetbrains.mps.generator.impl.query.GeneratorQueryProvider;
import jetbrains.mps.generator.runtime.TemplateDeclaration;
import jetbrains.mps.generator.runtime.TemplateMappingConfiguration;
import jetbrains.mps.generator.runtime.TemplateModel;
import jetbrains.mps.generator.runtime.TemplateModule;
import jetbrains.mps.generator.runtime.TemplateModuleBase;
import jetbrains.mps.generator.runtime.TemplateSwitchMapping;
import jetbrains.mps.project.ModuleId;
import jetbrains.mps.project.structure.modules.ModuleReference;
import jetbrains.mps.project.structure.modules.mappingpriorities.MappingPriorityRule;
import jetbrains.mps.project.structure.modules.mappingpriorities.RuleType;
import jetbrains.mps.smodel.SModelId;
import jetbrains.mps.smodel.SModelReference;
import jetbrains.mps.smodel.SNodePointer;
import jetbrains.mps.smodel.SNodeUtil;
import jetbrains.mps.smodel.language.LanguageRuntime;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.language.SLanguage;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeReference;
import org.jetbrains.mps.openapi.module.SModuleReference;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Artem Tikhomirov
*/
public class GenPlanTest {
private PriorityConflicts myConflicts;
private PartitioningSolver mySolver;
private MockTemplateModel myTemplateModel;
private MockTemplateModule myTemplateModule;
@Before
public void setup() {
myConflicts = new PriorityConflicts(Collections.emptyList());
mySolver = new PartitioningSolver(myConflicts);
myTemplateModule = new MockTemplateModule();
myTemplateModel = new MockTemplateModel(myTemplateModule, "MockTemplateModel");
}
/**
* A <= B
* B < C
*
* Expected:
* generators combined: {A,B} {C}
* standalone generators: {A} {B} {C}
*/
@Test
public void testWeakEdgeReplacedSimple() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addStrict(tmcB, tmcC);
//
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(3, phases.size());
List<Group> groupsPhase1 = phases.get(0).getGroups();
List<Group> groupsPhase2 = phases.get(1).getGroups();
List<Group> groupsPhase3 = phases.get(2).getGroups();
assertEquals(1, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
assertEquals(1, groupsPhase3.size());
assertEquals(new Group(tmcA), groupsPhase1.get(0));
assertEquals(new Group(tmcB), groupsPhase2.get(0));
assertEquals(new Group(tmcC), groupsPhase3.get(0));
}
/**
* A <= B
* B < C
* B <= D
* X < A
* Y <= A
*
* Expected:
* generators combined: {X} {A,B,Y} {C,D}
* standalone generators: {X,Y} {A} {B} {C,D}
*/
@Test
public void testWeakEdgeReplacedComplex() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
TemplateMappingConfiguration tmcD = newMapConfig("D", false);
TemplateMappingConfiguration tmcX = newMapConfig("X", false);
TemplateMappingConfiguration tmcY = newMapConfig("Y", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC, tmcD, tmcX, tmcY);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addStrict(tmcB, tmcC);
addWeak(tmcB, tmcD);
addStrict(tmcX, tmcA);
addWeak(tmcY, tmcA);
//
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(4, phases.size());
List<Group> groupsPhase1 = phases.get(0).getGroups();
List<Group> groupsPhase2 = phases.get(1).getGroups();
List<Group> groupsPhase3 = phases.get(2).getGroups();
List<Group> groupsPhase4 = phases.get(3).getGroups();
assertEquals(2, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
assertEquals(1, groupsPhase3.size());
assertEquals(2, groupsPhase4.size());
assertEquals(asSet(tmcX, tmcY), new HashSet<>(groupsPhase1));
//
assertEquals(new Group(tmcA), groupsPhase2.get(0));
assertEquals(new Group(tmcB), groupsPhase3.get(0));
//
assertEquals(asSet(tmcC, tmcD), new HashSet<>(groupsPhase4));
}
/**
* A == B
* B == C
* C == D
* E == D
* B < X
*
* Expected {ABCDE} {X}
*/
@Test
public void testMergeCoherentEdges() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
TemplateMappingConfiguration tmcD = newMapConfig("D", false);
TemplateMappingConfiguration tmcE = newMapConfig("E", false);
TemplateMappingConfiguration tmcX = newMapConfig("X", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC, tmcD, tmcE, tmcX);
mySolver.prepare(allConfigs);
addCoherentConfigs(tmcA, tmcB);
addCoherentConfigs(tmcB, tmcC);
addCoherentConfigs(tmcC, tmcD);
addCoherentConfigs(tmcE, tmcD);
addStrict(tmcB, tmcX);
//
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(2, phases.size());
List<Group> groupsPhase1 = phases.get(0).getGroups();
List<Group> groupsPhase2 = phases.get(1).getGroups();
assertEquals(1, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
ArrayList<Group> allGroups = new ArrayList<>();
for (TemplateMappingConfiguration mc : allConfigs) {
allGroups.add(new Group(mc));
}
assertEquals(new Group(allGroups).subtract(new Group(tmcX)), groupsPhase1.get(0));
assertEquals(new Group(tmcX), groupsPhase2.get(0));
}
/**
* A <= B
* B == C
*
* Expected:
* generators combined: {ABC} or {A} {BC} (two steps), but not {A,BC} (single steps with two unrelated groups)
* standalone generators: {A} {BC}
*/
@Test
public void testWeakWithCoherent_1() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addCoherentConfigs(tmcB, tmcC);
//
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(2, phases.size());
final List<Group> groups1 = phases.get(0).getGroups();
final List<Group> groups2 = phases.get(1).getGroups();
assertEquals(1, groups1.size());
assertEquals(1, groups2.size());
assertEquals(new Group(tmcA), groups1.get(0));
assertEquals(asSingleGroup(tmcB, tmcC), groups2.get(0));
}
/**
* Coherent mappings on both sides of weak rule
* A <= B
* A == B
*
* Expected: {AB}
*/
@Test
public void testWeakWithCoherent_2() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addCoherentConfigs(tmcA, tmcB);
//
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(1, phases.size());
final List<Group> groups = phases.get(0).getGroups();
assertEquals(groups.toString(), 1, groups.size());
assertEquals(new Group(tmcA).union(new Group(tmcB)), groups.get(0));
}
/**
* A < B
* A == C
* B == C
*/
@Test
public void testCoherentOnBothSidesOfStrictRule() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC);
mySolver.prepare(allConfigs);
addStrict(tmcA, tmcB);
addCoherentConfigs(tmcA, tmcC);
addCoherentConfigs(tmcB, tmcC);
assertFalse("[sanity]", myConflicts.hasConflicts());
mySolver.solve();
assertTrue(myConflicts.hasConflicts());
}
/**
* A <= B
* A == C
* B == C
* C < X
*
* Expected: {ABC} {X}
*/
@Test
public void testCoherentOnBothSidesOfWeakRule() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
TemplateMappingConfiguration tmcX = newMapConfig("X", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC, tmcX);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addStrict(tmcC, tmcX);
addCoherentConfigs(tmcA, tmcC);
addCoherentConfigs(tmcB, tmcC);
//
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(2, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
final List<Group> groupsPhase2 = phases.get(1).getGroups();
assertEquals(groupsPhase1.toString(), 1, groupsPhase1.size());
assertEquals(new Group(tmcA).union(new Group(tmcB)).union(new Group(tmcC)), groupsPhase1.get(0));
assertEquals(new Group(tmcX), groupsPhase2.get(0));
}
/**
* A and B are topPri == true, A not in any relation
* B <= C
* C <= D
*
* Expected:
* generators combined: {A, B} {C, D}
* standalone generators: {A, B} {C} {D}
*/
@Test
public void testTopPriorityComesFirst() {
TemplateMappingConfiguration tmcA = newMapConfig("A", true);
TemplateMappingConfiguration tmcB = newMapConfig("B", true);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
TemplateMappingConfiguration tmcD = newMapConfig("D", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC, tmcD);
mySolver.prepare(allConfigs);
addWeak(tmcB, tmcC);
addWeak(tmcC, tmcD);
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(3, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
final List<Group> groupsPhase2 = phases.get(1).getGroups();
final List<Group> groupsPhase3 = phases.get(2).getGroups();
assertEquals(2, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
assertEquals(1, groupsPhase3.size());
assertEquals(asSet(tmcA, tmcB), new HashSet<>(groupsPhase1));
assertEquals(new Group(tmcC), groupsPhase2.get(0));
assertEquals(new Group(tmcD), groupsPhase3.get(0));
}
/**
* A < B(topPri)
*
* Expected: conflicts reported
*/
@Test
public void testTopPriorityDependsOnLowPriorityStrict() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", true);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB);
mySolver.prepare(allConfigs);
addStrict(tmcA, tmcB);
mySolver.solve();
assertTrue(myConflicts.hasConflicts());
assertFalse(myConflicts.get(Kind.LoPriLocksHiPri).isEmpty());
}
/**
* A and B both top priority mc
* A < B
* A < C
*
* Expected: {A} {B} {C}
*/
@Test
public void testTopPrioDependsOnTopPrio() {
TemplateMappingConfiguration tmcA = newMapConfig("A", true);
TemplateMappingConfiguration tmcB = newMapConfig("B", true);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC);
mySolver.prepare(allConfigs);
addStrict(tmcA, tmcB);
addStrict(tmcA, tmcC);
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(3, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
final List<Group> groupsPhase2 = phases.get(1).getGroups();
final List<Group> groupsPhase3 = phases.get(2).getGroups();
assertEquals(1, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
assertEquals(1, groupsPhase2.size());
assertEquals(new Group(tmcA), groupsPhase1.get(0));
assertEquals(new Group(tmcB), groupsPhase2.get(0));
assertEquals(new Group(tmcC), groupsPhase3.get(0));
}
/**
* A <= B(topPri)
* A < C
*
* Expected: conflicts reported
*/
@Test
public void testTopPriorityDependsOnLowPriorityWeak() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", true);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addStrict(tmcA, tmcC);
mySolver.solve();
assertTrue(myConflicts.hasConflicts());
assertFalse(myConflicts.get(Kind.LoPriLocksHiPri).isEmpty());
}
/**
* A (topPri) == B
*
* Expected: conflicts reported
*/
@Test
public void testTopPriorityCoherentWithLowPriority() {
TemplateMappingConfiguration tmcA = newMapConfig("A", true);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB);
mySolver.prepare(allConfigs);
addCoherentConfigs(tmcA, tmcB);
mySolver.solve();
assertTrue(myConflicts.hasConflicts());
assertFalse(myConflicts.get(Kind.CoherentPrioMix).isEmpty());
}
/**
* A <= B,
* A < B
*
* Expected: {A} {B}
*/
@Test
public void testSameEdgeBothWeakAndStrict() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addStrict(tmcA, tmcB);
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(2, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
final List<Group> groupsPhase2 = phases.get(1).getGroups();
assertEquals(1, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
assertEquals(new Group(tmcA), groupsPhase1.get(0));
assertEquals(new Group(tmcB), groupsPhase2.get(0));
}
/**
* A, B, C < D
* B == E
*
* Expected: {A, C, BE} {D}
*/
@Test
public void testReplaceCoherent_1() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
TemplateMappingConfiguration tmcD = newMapConfig("D", false);
TemplateMappingConfiguration tmcE = newMapConfig("E", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC, tmcD, tmcE);
mySolver.prepare(allConfigs);
addStrict(tmcA, tmcD);
addStrict(tmcB, tmcD);
addStrict(tmcC, tmcD);
addCoherentConfigs(tmcB, tmcE);
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(2, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
final List<Group> groupsPhase2 = phases.get(1).getGroups();
assertEquals(3, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
final Set<Group> expectedPhase1 = asSet(tmcA, tmcC);
expectedPhase1.add(new Group(tmcB).union(new Group(tmcE)));
assertEquals(expectedPhase1, new HashSet<>(groupsPhase1));
assertEquals(new Group(tmcD), groupsPhase2.get(0));
}
/**
* Check we replace coherent groups on both sides of a rule
* (first coherent group updates the edge, and second coherent group shall update the edge once again)
* A < B
* A == C
* B == D
*
* Expected: {AC} {BD}
*/
@Test
public void testReplaceCoherent_2() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
TemplateMappingConfiguration tmcD = newMapConfig("D", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC, tmcD);
mySolver.prepare(allConfigs);
addStrict(tmcA, tmcB);
addCoherentConfigs(tmcA, tmcC);
addCoherentConfigs(tmcB, tmcD);
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(2, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
final List<Group> groupsPhase2 = phases.get(1).getGroups();
assertEquals(1, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
assertEquals(asSingleGroup(tmcA, tmcC), groupsPhase1.get(0));
assertEquals(asSingleGroup(tmcB, tmcD), groupsPhase2.get(0));
}
/**
* Check if replacement of coherent yields identical rules (and alg doesn't fail/hang)
* A < C
* B < C
* A == B
*
* Expected: {AB} {C}
*/
@Test
public void testReplaceCoherent_3() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC);
mySolver.prepare(allConfigs);
addStrict(tmcA, tmcC);
addStrict(tmcB, tmcC);
addCoherentConfigs(tmcA, tmcB);
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(2, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
final List<Group> groupsPhase2 = phases.get(1).getGroups();
assertEquals(1, groupsPhase1.size());
assertEquals(1, groupsPhase2.size());
assertEquals(asSingleGroup(tmcA, tmcB), groupsPhase1.get(0));
assertEquals(new Group(tmcC), groupsPhase2.get(0));
}
/**
* A <= B
* B <= C
* C <= A
*
* Expected: {ABC}
*/
@Test
public void testWeakCycle() {
TemplateMappingConfiguration tmcA = newMapConfig("A", false);
TemplateMappingConfiguration tmcB = newMapConfig("B", false);
TemplateMappingConfiguration tmcC = newMapConfig("C", false);
final List<TemplateMappingConfiguration> allConfigs = Arrays.asList(tmcA, tmcB, tmcC);
mySolver.prepare(allConfigs);
addWeak(tmcA, tmcB);
addWeak(tmcB, tmcC);
addWeak(tmcC, tmcA);
final List<GenerationPhase> phases = mySolver.solve();
assertFalse(myConflicts.hasConflicts());
assertEquals(1, phases.size());
final List<Group> groupsPhase1 = phases.get(0).getGroups();
assertEquals(1, groupsPhase1.size());
assertEquals(asSingleGroup(tmcA, tmcB, tmcC), groupsPhase1.get(0));
}
/**
* L1, G1: A
* L2, G2: B
* A < B
*
* L3, G3: C, D, E, F. usedLanguages: L1, L2
* B <= C
* B <= E
* D < B
* F == B
* Implicit rule (due to usedLanguage L1): C, D, E, F <= A
*
* FIXME usedLanguage are respected 'per generator', not 'per MC'. If we could do that per MC, implicit rule would be much less demanding
*/
@Test
public void testImplicitPriorities() {
MockTemplateModel g1 = new MockTemplateModel(myTemplateModule, "G1");
MockTemplateModel g2 = new MockTemplateModel(myTemplateModule, "G2");
MockTemplateModel g3 = new MockTemplateModel(myTemplateModule, "G3");
TemplateMappingConfiguration tmcA = newMapConfig(g1, "A");
TemplateMappingConfiguration tmcB = newMapConfig(g2, "B");
TemplateMappingConfiguration tmcC = newMapConfig(g3, "C");
TemplateMappingConfiguration tmcD = newMapConfig(g3, "D");
TemplateMappingConfiguration tmcE = newMapConfig(g3, "E");
TemplateMappingConfiguration tmcF = newMapConfig(g3, "F");
mySolver.prepare(Arrays.asList(tmcA, tmcB, tmcC, tmcD, tmcE, tmcF));
addStrict(tmcA, tmcB);
addWeak(tmcB, tmcC);
addWeak(tmcB, tmcE);
addStrict(tmcD, tmcB);
addCoherentConfigs(tmcF, tmcB);
addWeak(tmcC, tmcA);
addWeak(tmcD, tmcA);
addWeak(tmcE, tmcA);
addWeak(tmcF, tmcA);
final List<GenerationPhase> phases = mySolver.solve();
print(phases);
for (Conflict c : myConflicts.getConflicts()) {
System.out.println(c.getText());
}
final List<Conflict> cycles = myConflicts.getConflicts(Collections.singletonList(Kind.Cycle));
assertEquals(1, cycles.size());
}
private void addWeak(TemplateMappingConfiguration sooner, TemplateMappingConfiguration later) {
mySolver.establishDependency(Collections.singleton(sooner), Collections.singleton(later), getWeakRule());
}
private void addStrict(TemplateMappingConfiguration sooner, TemplateMappingConfiguration later) {
mySolver.establishDependency(Collections.singleton(sooner), Collections.singleton(later), getStrictRule());
}
private void addCoherentConfigs(TemplateMappingConfiguration... mc) {
mySolver.registerCoherent(Arrays.asList(mc), getStrictRule());
}
private TemplateMappingConfiguration newMapConfig(String name, boolean topPri) {
return new MockMapConfig(myTemplateModel, createMapConfigNode(name), name, topPri);
}
private TemplateMappingConfiguration newMapConfig(MockTemplateModel model, String name) {
return new MockMapConfig(model, createMapConfigNode(name), name, false);
}
private static void print(List<GenerationPhase> r) {
for (GenerationPhase steps : r) {
System.out.print("Step: ");
for (Group group : steps.getGroups()) {
final Collection<TemplateMappingConfiguration> elements = group.getElements();
if (elements.size() > 1) {
System.out.print("{ ");
}
for (TemplateMappingConfiguration tmc : elements) {
System.out.print(tmc.getName());
System.out.print(", ");
}
if (elements.size() > 1) {
System.out.print("} ");
}
}
System.out.println();
}
}
private static MappingPriorityRule getWeakRule() {
MappingPriorityRule weakRule = new MappingPriorityRule();
weakRule.setType(RuleType.AFTER_OR_TOGETHER);
return weakRule;
}
private static MappingPriorityRule getStrictRule() {
MappingPriorityRule strictRule = new MappingPriorityRule();
strictRule.setType(RuleType.STRICTLY_AFTER);
return strictRule;
}
private static Set<Group> asSet(TemplateMappingConfiguration... tmc) {
HashSet<Group> rv = new HashSet<>();
for (TemplateMappingConfiguration mc : tmc) {
rv.add(new Group(mc));
}
return rv;
}
private static Group asSingleGroup(TemplateMappingConfiguration... tmc) {
Group rv = new Group(tmc[0]);
for (int i = 1, x = tmc.length; i < x; i++) {
rv = rv.union(new Group(tmc[i]));
}
return rv;
}
private static SNode createMapConfigNode(String name) {
SNode n = new jetbrains.mps.smodel.SNode(RuleUtil.concept_MappingConfiguration);
n.setProperty(SNodeUtil.property_INamedConcept_name, name);
return n;
}
private static class MockMapConfig extends TemplateMappingConfigurationInterpreted {
private final SNodeReference myNodePtr;
private final String myName;
private final boolean myTopPri;
MockMapConfig(MockTemplateModel model, SNode mcNode, String name, boolean topPri) {
super(model, mcNode);
// name and topPri are direct values, not through SNode.getProperty as it
// name requires node to be isSubConceptOf(INamedConcept), which requires concept registry et al.
// topPri involves constraints - too much, imo.
myName = name;
myTopPri = topPri;
myNodePtr = new SNodePointer(model.getSModelReference(), mcNode.getNodeId());
model.registerMapConfig(this);
}
@Override
public String getName() {
return myName;
}
@Override
public boolean isTopPriority() {
return myTopPri;
}
@Override
public SNodeReference getMappingNode() {
return myNodePtr;
}
}
private static class MockTemplateModule extends TemplateModuleBase {
private final SModuleReference myModuleReference;
MockTemplateModule() {
myModuleReference = new ModuleReference("MockModule", ModuleId.regular());
}
@NotNull
@Override
public SModuleReference getModuleReference() {
return myModuleReference;
}
@Override
public Collection<SLanguage> getTargetLanguages() {
return Collections.emptyList();
}
@Override
public String getAlias() {
return getClass().getSimpleName();
}
@NotNull
@Override
public LanguageRuntime getSourceLanguage() {
throw new UnsupportedOperationException();
}
}
private static class MockTemplateModel implements TemplateModel {
private final MockTemplateModule myModule;
private final String myName;
private final SModelReference myModelRef;
private static final List<TemplateMappingConfiguration> myMC = new ArrayList<>();
MockTemplateModel(MockTemplateModule tm, String name) {
myModule = tm;
myName = name;
myModelRef = new SModelReference(tm.getModuleReference(), SModelId.generate(), name);
}
@Override
public String getLongName() {
return myName;
}
@Override
public org.jetbrains.mps.openapi.model.SModelReference getSModelReference() {
return myModelRef;
}
@Override
public Collection<TemplateSwitchMapping> getSwitches() {
return Collections.emptyList();
}
@Override
public Collection<TemplateMappingConfiguration> getConfigurations() {
return Collections.unmodifiableCollection(myMC);
}
@Override
public TemplateDeclaration loadTemplate(SNodeReference template, Object... arguments) {
return null;
}
@Override
public TemplateModule getModule() {
return myModule;
}
@Override
public GeneratorQueryProvider getQueryProvider() {
throw new UnsupportedOperationException();
}
/*package*/ void registerMapConfig(@NotNull TemplateMappingConfiguration mc) {
myMC.add(mc);
}
}
}