/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * TypeVariableRenamer_Test.java * Created: Sep 29, 2007 * By: Joseph Wong */ package org.openquark.cal.compiler; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.openquark.cal.CALPlatformTestModuleNames; import org.openquark.cal.compiler.CompilerMessage.Severity; import org.openquark.cal.compiler.IdentifierOccurrence.Binding; import org.openquark.cal.compiler.IdentifierOccurrenceFinder.FinderState; import org.openquark.cal.compiler.IdentifierResolver.SymbolTable; import org.openquark.cal.compiler.IdentifierResolver.TypeVariableScope; import org.openquark.cal.compiler.IdentifierResolver.VisitorArgument; import org.openquark.cal.module.Cal.Core.CAL_Prelude; import org.openquark.cal.runtime.MachineType; import org.openquark.cal.services.BasicCALServices; import org.openquark.cal.services.CALServicesTestUtilities; import org.openquark.util.Pair; /** * JUnit test cases for the {@link TypeVariableRenamer}. * * @author Joseph Wong */ public class TypeVariableRenamer_Test extends TestCase { /** * A copy of CAL services for use in the test cases */ private static BasicCALServices leccServices; /** * Constructor for TypeVariableRenamer_Test. * * @param name * the name of the test. */ public TypeVariableRenamer_Test(String name) { super(name); } /** * @return a test suite containing all the test cases for testing CAL source * generation. */ public static Test suite() { TestSuite suite = new TestSuite(TypeVariableRenamer_Test.class); return new TestSetup(suite) { protected void setUp() { oneTimeSetUp(); } protected void tearDown() { oneTimeTearDown(); } }; } /** * Performs the setup for the test suite. */ private static void oneTimeSetUp() { leccServices = CALServicesTestUtilities.getCommonCALServices(MachineType.LECC, "cal.platform.test.cws"); } /** * Performs the tear down for the test suite. */ private static void oneTimeTearDown() { leccServices = null; } public void testAllShadowingIssues() { String template = "module " + CALPlatformTestModuleNames.CALRenaming_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + ";\n" + "class (Prelude.Ord %c) => C1 %c where\n" + " m1a :: %c -> @w -> %c;\n" + " m1b :: %c;\n" + " ;\n" + "class C2 @b where\n" + " m2a :: @b -> %x;\n" + " m2b :: @b -> b_1;\n" + " ;\n" + "data T @e %f =\n" + " D1 foo::@e bar::%f |\n" + " D2 foo::%f bar::(@e->%f->@e)\n" + " ;\n" + "func :: %p -> @q -> r;\n" + "func =\n" + " let" + " inner :: p -> q_1;\n" + " inner = Prelude.undefined;\n" + " in\n" + " Prelude.undefined;\n"; final String oldSourceText = template .replaceAll("%c", "c").replaceAll("@w", "w") .replaceAll("%x", "x").replaceAll("@b", "b") .replaceAll("%f", "f").replaceAll("@e", "e") .replaceAll("%p", "p").replaceAll("@q", "q").replaceAll("##", "@"); final ModuleName moduleName = CALPlatformTestModuleNames.CALRenaming_Test_Support1; final ModuleTypeInfo moduleTypeInfo = leccServices.getWorkspaceManager().getModuleTypeInfo(moduleName); CompilerMessageLogger logger = new MessageLogger(); // Because type variable identifier infos are invalidated under source range, therefore // there need to be recalculated between renaming passes final List<Pair<String, String>> targets = new ArrayList<Pair<String, String>>(); targets.add(Pair.make("c", "w")); targets.add(Pair.make("x", "b")); targets.add(Pair.make("f", "e")); targets.add(Pair.make("p", "q")); String renamedSourceText = oldSourceText; SourceModifier sourceModifier; for (final Pair<String, String> target : targets) { final Map<IdentifierInfo.TypeVariable, String> renamings = new LinkedHashMap<IdentifierInfo.TypeVariable, String>(); IdentifierOccurrenceFinder<Void> finder = new IdentifierOccurrenceFinder<Void>(moduleName) { private boolean seenAlready = false; @Override protected void handleTypeVariableBinding(Binding<IdentifierInfo.TypeVariable> binding, TypeVariableScope scope) { final IdentifierInfo.TypeVariable identifierInfo = binding.getIdentifierInfo(); final String typeVarName = identifierInfo.getTypeVarName(); if (typeVarName.equals(target.fst()) && !seenAlready) { seenAlready = true; renamings.put(identifierInfo, target.snd()); } } }; final SourceModel.ModuleDefn moduleDefn = SourceModelUtilities.TextParsing.parseModuleDefnIntoSourceModel(renamedSourceText, logger); assertNoCompilationErrors(logger); moduleDefn.accept(finder, VisitorArgument.make(SymbolTable.makeRoot(moduleName, IdentifierResolver.makeContext(moduleTypeInfo)), FinderState.make())); for (final Map.Entry<IdentifierInfo.TypeVariable, String> renaming : renamings.entrySet()) { sourceModifier = TypeVariableRenamer.getSourceModifier(moduleTypeInfo, renamedSourceText, renaming.getKey(), renaming.getValue(), logger); assertNoCompilationErrors(logger); renamedSourceText = sourceModifier.apply(renamedSourceText); } } final String newSourceText = template .replaceAll("%c", "w").replaceAll("@w", "w_1") .replaceAll("%x", "b").replaceAll("@b", "b_2") .replaceAll("%f", "e").replaceAll("@e", "e_1") .replaceAll("%p", "q").replaceAll("@q", "q_1").replaceAll("##", "@"); assertEquals(newSourceText, renamedSourceText); } private void assertNoCompilationErrors(final CompilerMessageLogger logger) { assertEquals("Compilation error", Collections.EMPTY_LIST, logger.getCompilerMessages(Severity.ERROR)); } }