/* * 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. */ /* * ImportCleaner_Test.java * Creation date: (Feb 14, 2006) * By: James Wright */ package org.openquark.cal.compiler; 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.module.Cal.Collections.CAL_List; import org.openquark.cal.module.Cal.Core.CAL_Bits; import org.openquark.cal.module.Cal.Core.CAL_Char; 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.cal.services.CALWorkspace; /** * Tests for the ImportCleaner functionality. * * For convenience, these tests usually include only a portion of the relevant * supporting CAL modules as their "module text". * * @author James Wright */ public class ImportCleaner_Test extends TestCase { /** A cached reference to the CAL test services */ private static BasicCALServices leccCALServices; /** A cached reference to a compiled CAL workspace */ private static CALWorkspace workspace; /** * @return a test suite containing all the test cases for testing CAL import refactoring */ public static Test suite() { TestSuite suite = new TestSuite(ImportCleaner_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() { leccCALServices = CALServicesTestUtilities.getCommonCALServices(MachineType.LECC, "cal.platform.test.cws"); workspace = leccCALServices.getCALWorkspace(); } /** * Performs the tear down for the test suite. */ private static void oneTimeTearDown() { leccCALServices = null; workspace = null; } /** * Simple test that functions with no unqualified references are properly removed from * import-using clauses. * */ public void testRedundantUsingFunctionRemoval() { String origModuleText = "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + ";\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = head, tail, subList;\n" + " ;\n" + "/* a comment */\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support1, origModuleText, false, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); String newModuleText = sourceModifier.apply(origModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed( "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + ";\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = tail;\n" + " ;\n" + "/* a comment */\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;", newModuleText); String undoneModuleText = sourceModifier.undo(newModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed(origModuleText, undoneModuleText); } /** * Test that comments are preserved in unmodified import statements. */ public void testCommentPreservation() { String origModuleText = "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "/* comment 1*/ import /* comment 2 */ " + CAL_Prelude.MODULE_NAME + ";\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = head, tail, subList;\n" + " ;\n" + "/* a comment 3*/\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support1, origModuleText, false, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); String newModuleText = sourceModifier.apply(origModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed( "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "/* comment 1*/ import /* comment 2 */ " + CAL_Prelude.MODULE_NAME + ";\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = tail;\n" + " ;\n" + "/* a comment 3*/\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;", newModuleText); String undoneModuleText = sourceModifier.undo(newModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed(undoneModuleText, origModuleText); } /** * Test that we don't introduce any changes when no imports need to be altered. * */ public void testNullRefactoring() { String origModuleText = "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import /*comment */ " + CAL_Prelude.MODULE_NAME + ";\n" + "foo = 55;"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support1, origModuleText, false, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); assertEquals(0, sourceModifier.getNSourceModifications()); String newModuleText = sourceModifier.apply(origModuleText); assertEquals(newModuleText, origModuleText); String undoneModuleText = sourceModifier.undo(newModuleText); assertEquals(origModuleText, undoneModuleText); } /** * Test that the removal of entire import statements works. * */ public void testImportRemoval() { String origModuleText = "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support2 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + ";\n" + "import " + CAL_List.MODULE_NAME + ";\n" + "import " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + " using\n" + " function = exportedFunction; /* this whole import should vanish */\n" + " typeClass = ExportedClass;\n" + " ;\n" + "import " + CAL_Bits.MODULE_NAME + "; // This should stay, since Bits contains otherwise-invisible instances\n" + "import " + CAL_Char.MODULE_NAME + "; // Char imports Debug, which contains otherwise-invisible instances once " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + " is gone\n" + "doStrictFold = " + CAL_List.MODULE_NAME + ".foldLeftStrict;\n"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support2, origModuleText, false, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); String newModuleText = sourceModifier.apply(origModuleText); assertEquals( "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support2 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + ";\n" + "import " + CAL_List.MODULE_NAME + ";\n" + "\n" + "import " + CAL_Bits.MODULE_NAME + "; // This should stay, since Bits contains otherwise-invisible instances\n" + "import " + CAL_Char.MODULE_NAME + "; // Char imports Debug, which contains otherwise-invisible instances once " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + " is gone\n" + "doStrictFold = " + CAL_List.MODULE_NAME + ".foldLeftStrict;\n", newModuleText); } /** * Test import cleanup and multi-line formatting and grouping of multiple * items into a single item. * */ public void testImportUsingCleanupWithGrouping() { String origModuleText = "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + "function = concat, equals, error, fromJust, fst, intToString, isNothing, isEmpty;\n" + "function = max, not, output, seq, snd, field1, field2, field3, upFrom, upFromTo, fromMaybe, notANumber, isNotANumber, isJust, abs, multiply, min, field4;\n" + "dataConstructor =\n" + " Cons, EQ, False, GT, Just, LT, Left, Nil, Nothing, Right, True;" + " ;\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = head, tail, subList;\n" + " ;\n" + "/* a comment */\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;" + "private referencePreludeFunctions =\n" + " (concat, equals, error, fromJust, fst, intToString, isNothing, isEmpty, max, not, output, seq, snd, field1, field2, field3, upFrom, upFromTo, fromMaybe, notANumber, isNotANumber, isJust, abs, multiply, min, field4);" + "private referencePreludeDataconses =" + " (False, True, LT, EQ, GT, Nil, Cons, Nothing, Just, Left, Right);"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support1, origModuleText, false, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); String newModuleText = sourceModifier.apply(origModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed( "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + " dataConstructor =\n" + " False, True, Left, Right, Nil, Cons, Nothing, Just, LT, EQ, GT;\n" + " function =\n" + " abs, concat, equals, error, field1, field2, field3, field4, fromJust,\n" + " fromMaybe, fst, intToString, isEmpty, isJust, isNotANumber, isNothing,\n" + " max, min, multiply, not, notANumber, output, seq, snd, upFrom, upFromTo;\n" + " ;\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = tail;\n" + " ;\n" + "/* a comment */\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;" + "private referencePreludeFunctions =\n" + " (concat, equals, error, fromJust, fst, intToString, isNothing, isEmpty, max, not, output, seq, snd, field1, field2, field3, upFrom, upFromTo, fromMaybe, notANumber, isNotANumber, isJust, abs, multiply, min, field4);" + "private referencePreludeDataconses =" + " (False, True, LT, EQ, GT, Nil, Cons, Nothing, Just, Left, Right);", newModuleText); } /** * Test that the preserve-items option does in fact preserve items, except those that would * become empty. * */ public void testImportUsingCleanupWithoutGrouping() { String origModuleText = "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + "function = negate;\n" + "function = concat, equals, error, fromJust, fst, intToString, isNothing, isEmpty;\n" + "function = max, not, output, seq, snd, field1, field2, field3, upFrom, upFromTo, fromMaybe, notANumber, isNotANumber, isJust, abs, multiply, min, field4;\n" + "dataConstructor = Cons, EQ, False, GT, Just, LT, Left, Nil, Nothing, Right, True;" + " ;\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = head, tail, subList;\n" + " ;\n" + "/* a comment */\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;" + "private referencePreludeFunctions =\n" + " (concat, equals, error, fromJust, fst, intToString, isNothing, isEmpty, max, not, output, seq, snd, field1, field2, field3, upFrom, upFromTo, fromMaybe, notANumber, isNotANumber, isJust, abs, multiply, min, field4);" + "private referencePreludeDataconses =" + " (False, True, LT, EQ, GT, Nil, Cons, Nothing, Just, Left, Right);"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support1, origModuleText, true, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); String newModuleText = sourceModifier.apply(origModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed( "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + " function =\n" + " concat, equals, error, fromJust, fst, intToString, isEmpty, isNothing;\n" + " function =\n" + " abs, field1, field2, field3, field4, fromMaybe, isJust, isNotANumber,\n" + " max, min, multiply, not, notANumber, output, seq, snd, upFrom, upFromTo;\n" + " dataConstructor =\n" + " False, True, Left, Right, Nil, Cons, Nothing, Just, LT, EQ, GT;\n" + " ;\n" + "import " + CAL_List.MODULE_NAME + " using\n" + " function = tail;\n" + " ;\n" + "/* a comment */\n" + "listRoundTrip x = " + CAL_List.MODULE_NAME + ".head x : tail x;" + "private referencePreludeFunctions =\n" + " (concat, equals, error, fromJust, fst, intToString, isNothing, isEmpty, max, not, output, seq, snd, field1, field2, field3, upFrom, upFromTo, fromMaybe, notANumber, isNotANumber, isJust, abs, multiply, min, field4);" + "private referencePreludeDataconses =" + " (False, True, LT, EQ, GT, Nil, Cons, Nothing, Just, Left, Right);", newModuleText); } /** * Test that unqualified references to data constructors are not sufficient to prevent * import-using entries for type constructors of the same name from being removed. * */ public void testImportUsingConsNameDistinction1() { String origModuleText = "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + "dataConstructor = Unit;\n" + "typeConstructor = Unit;\n" + " ;\n" + "refDataCons = Unit;"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support1, origModuleText, true, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); String newModuleText = sourceModifier.apply(origModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed( "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + " dataConstructor = Unit;\n" + " ;\n" + "refDataCons = Unit;", newModuleText); } /** * Test that unqualified references to type constructors are not sufficient to prevent * import-using entries for data constructors of the same name from being removed. * */ public void testImportUsingConsNameDistinction2() { String origModuleText = "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + "dataConstructor = Unit;\n" + "typeConstructor = Unit;\n" + " ;\n" + "refTypeCons :: Unit;\n" + "refTypeCons = ();"; CompilerMessageLogger logger = new MessageLogger(); SourceModifier sourceModifier = ImportCleaner.getSourceModifier_cleanImports(workspace.asModuleContainer(), CALPlatformTestModuleNames.ImportCleaner_Test_Support1, origModuleText, true, logger); assertTrue(logger.getMaxSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0); String newModuleText = sourceModifier.apply(origModuleText); CompilerTestUtilities.assertEqualsCanonicalLineFeed( "/** module-level comments */\n" + "module " + CALPlatformTestModuleNames.ImportCleaner_Test_Support1 + ";\n" + "import " + CAL_Prelude.MODULE_NAME + " using\n" + " typeConstructor = Unit;\n" + " ;\n" + "refTypeCons :: Unit;\n" + "refTypeCons = ();", newModuleText); } }