| /******************************************************************************* |
| * Copyright (c) 2005, 2016 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| |
| *******************************************************************************/ |
| package org.eclipse.dltk.ruby.core.tests.rewriter; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| |
| import org.eclipse.core.resources.IncrementalProjectBuilder; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.dltk.ast.declarations.ModuleDeclaration; |
| import org.eclipse.dltk.core.tests.model.AbstractModelTests; |
| import org.eclipse.dltk.ruby.core.tests.Activator; |
| import org.eclipse.dltk.ruby.internal.parsers.jruby.ASTUtils; |
| |
| /** |
| * @author mhowe |
| * |
| * The tests in this test case are intended to test class def's, type ref's, method def's, method ref's, block's, variable def's, variable ref's, hash |
| * expressions (very common in Ruby), expressions or statement. The tests don't go into detail for specific AST's, such as for, if etc. The intent here is to |
| * define the common top level AST's required for a majority of work with a rewriter, such as fix ups, re-factorings, renames, insertions/removal of high level |
| * elements at various points etc. |
| * |
| * The tests are intended to exercise the ability to locate a specific AST (such as a block, method def, statement etc) and then modify that AST or insert a new |
| * AST before or after the discovered AST. These are common use cases for modifying code from an AST perspective. |
| * |
| * The first pass of this test case uses ModuleDeclaration as a starting point but this is for demonstration only, no restriction on the API is suggested by |
| * this. ModuleDeclaration should be replaced with whatever is appropriate from the real API once created. These tests are fairly simple either using ruby files |
| * defined in the associated workspace or if the test is simple enough from strings in the test itself. Also many of tests so far are just method stubs with |
| * descriptive names to be filled in as the rewriter evolves. All tests require the rewriter API to be filled in. The checkResults method always fails, this |
| * requires converting an AST to a string and then comparing with the expected result. |
| * |
| * Once this stage of the rewriter is complete more test cases should be written which test the specific detailed AST's not covered by the tests in this test |
| * case. |
| */ |
| public class RewriterTests extends AbstractModelTests { |
| |
| private static final String PATH_PREFIX = "/workspace/rewriter/"; |
| private static final String SRC_PROJECT = "rewriter"; |
| |
| public RewriterTests(String name) { |
| super(Activator.PLUGIN_ID, name); |
| } |
| |
| @Override |
| public void setUpSuite() throws Exception { |
| setUpScriptProject(SRC_PROJECT); |
| super.setUpSuite(); |
| waitUntilIndexesReady(); |
| ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor()); |
| } |
| |
| @Override |
| public void tearDownSuite() throws Exception { |
| deleteProject(SRC_PROJECT); |
| super.tearDownSuite(); |
| } |
| |
| /////////////////////////////////////////////////////// |
| //Series of tests for adding various types of AST's |
| /////////////////////////////////////////////////////// |
| |
| /** |
| * Start with empty file and a header comment |
| * |
| */ |
| public void testAddCommentToEmptyScript() throws IOException { |
| String content = loadContent(PATH_PREFIX + "empty_script.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| |
| //add header to to ast |
| |
| checkResults(ast, loadContent(PATH_PREFIX + "empty_script_with_header.rb")); |
| } |
| |
| /** |
| * Start with empty file and add class declaration |
| * |
| */ |
| public void testAddSimpleClassToEmptyScript() throws IOException { |
| String content = loadContent(PATH_PREFIX + "empty_script.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| //add class "Simple" after comment |
| checkResults(ast, loadContent(PATH_PREFIX + "simple_class.rb")); |
| } |
| |
| /** |
| * Start with empty file and add class declaration |
| * |
| */ |
| public void testAddClassAfterHeader() throws IOException { |
| String content = loadContent(PATH_PREFIX + "empty_script_with_header.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| //add class "Simple" after comment |
| checkResults(ast, loadContent(PATH_PREFIX + "simple_class_with_header.rb")); |
| } |
| |
| /** |
| */ |
| public void testAddInnerClass() throws IOException { |
| String content = loadContent(PATH_PREFIX + "simple_class.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| //classAst.newClass("Inner"); |
| checkResults(ast, loadContent(PATH_PREFIX + "simple_nested_class.rb")); |
| } |
| |
| /** |
| * Insert new method before first method |
| * |
| * @throws IOException |
| */ |
| public void testInsertMethodBeforeFirstMethod() throws IOException { |
| String content = loadContent(PATH_PREFIX + "simple1.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| //insert new_method as first method |
| checkResults(ast, loadContent(PATH_PREFIX + "simple1a.result")); |
| } |
| |
| /** |
| * Insert method after specific method |
| * |
| * @throws IOException |
| */ |
| public void testInsertMethodAfterMethod() throws IOException { |
| String content = loadContent(PATH_PREFIX + "simple1.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| //insert new_method after method m1 |
| checkResults(ast, loadContent(PATH_PREFIX + "simple1b.result")); |
| } |
| |
| /** |
| * Insert method before specific method |
| * |
| * @throws IOException |
| */ |
| public void testInsertMethodBeforeMethod() throws IOException { |
| String content = loadContent(PATH_PREFIX + "simple1.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| //insert new_method before method m2 |
| checkResults(ast, loadContent(PATH_PREFIX + "simple1b.result")); |
| } |
| |
| /** |
| * Append method after last method |
| * |
| * @throws IOException |
| */ |
| public void testAppendMethod() throws IOException { |
| String content = loadContent(PATH_PREFIX + "simple1.rb"); |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| //append new_method after last method |
| checkResults(ast, loadContent(PATH_PREFIX + "simple1c.result")); |
| } |
| |
| /** |
| * Tests discovering a block and then inserting a method call as the first call in that block |
| */ |
| public void testInsertAsFirstMethodCallInBlock() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering a block and then inserting a method call as the last call in that block |
| */ |
| public void testInsertAsLastMethodCallInBlock() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering a method definition and then inserting a method call as the first call in that block |
| */ |
| public void testInsertAsFirstMethodCallInMethodDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering a method definition and then inserting a method call as the last call in that block |
| */ |
| public void testInsertAsLastMethodCallInMetohdDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering a specific statement and then inserting a method call before that statement |
| */ |
| public void testMethodCallBeforeStatement() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering a specific statement and then inserting a method call after that statement |
| */ |
| public void testMethodCallAfterStatement() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests adding a key/value pair to a hash expression |
| */ |
| public void testAddKeyValuePairToHash() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a new parameter as the first parameter to a method def |
| */ |
| public void testInsertFirstParameterToMethodDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a new parameter as the last parameter to a method def |
| */ |
| public void testInsertLastParameterToMethodDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a before a block in a method def |
| */ |
| public void testInsertBeforeBlockInMethodDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a parameter as a specific parameter in a method def, i.e. test adding a parameter between parameter 0 and parameter 1 |
| */ |
| public void testInsertParameterInSpecificPosInMethodDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a parameter as the first parameter in a method call |
| */ |
| public void testInsertFirstParameterToMethodCall() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a parameter as the last parameter in a method call |
| */ |
| public void testInsertLastParameterToMethodCall() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a parameter before the block in a method call (similar to appending a parameter as the last parameter but specifically tests the case where |
| * a block is used) |
| */ |
| public void testInsertBeforeBlockInMethodCall() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests inserting a parameter as a specific parameter in a method call, i.e. test adding a parameter between parameter 0 and parameter 1 |
| */ |
| public void testInsertParameterInSpecificPosInMethodCall() { |
| assertTrue(false); |
| } |
| |
| /////////////////////////////////////////////////////// |
| //Series of tests for modifying references |
| /////////////////////////////////////////////////////// |
| /** |
| * Change variable reference |
| */ |
| public void testChangeClassVariableReference() { |
| String content = "@@class_var = 'hello'"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //change @var to @new_var |
| checkResults(ast, "@@new_class_var = 'hello')"); |
| } |
| |
| /** |
| * Change variable reference |
| */ |
| public void testChangeInstanceVariableReference() { |
| String content = "puts(@instance_var = 'hello')"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //change @var to @new_var |
| checkResults(ast, "puts(@new_instance_var = 'hello')"); |
| } |
| |
| /** |
| * Change variable reference |
| */ |
| public void testChangeVariableReference() { |
| String content = "puts(var = 'hello')"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //change @var to @new_var |
| checkResults(ast, "puts(new_var = 'hello')"); |
| } |
| |
| /** |
| * Change type reference |
| */ |
| public void testChangeTypeReference() { |
| String content = "@var = Stringx.new"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //change type reference Stringx to String |
| checkResults(ast, "@var = String.new"); |
| } |
| |
| /** |
| * Change method reference |
| */ |
| public void testChangeMethodReference() { |
| String content = "@var = String.newx"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //change method reference newx to new |
| checkResults(ast, "@var = String.new"); |
| } |
| |
| /** |
| * Tests changing a symbol reference |
| */ |
| public void testChangeSymbolReference() { |
| String content = "var = :my_symbol"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //change symbol ref from :my_symbol to :your_symbol |
| checkResults(ast, "var = :your_symbol"); |
| } |
| |
| /** |
| * Tests changing a string literal reference |
| */ |
| public void testChangeStringLiteral() { |
| String content = "var = 'my_string'"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| checkResults(ast, "var = 'your_string'"); |
| } |
| |
| //TODO |
| public void testChangeNumericLiteral() throws IOException { |
| String content = "var = 123"; |
| ModuleDeclaration ast = ASTUtils.getAST(content.toCharArray()); |
| //modify ast |
| checkResults(ast, "var = 4567"); |
| } |
| |
| /** |
| * Test adding parenthesis around a method call (tests finding all the parameters to a call) |
| */ |
| public void testAddParenthesisAroundMethodCall() { |
| assertTrue(false); |
| } |
| |
| /////////////////////////////////////////////////////// |
| //Series of tests for modifying whitespace and delimeters |
| /////////////////////////////////////////////////////// |
| public void testRemoveLeadingWhiteSpace() { |
| assertTrue(false); |
| } |
| |
| public void testRemoveTrailingWhiteSpace() { |
| assertTrue(false); |
| } |
| |
| public void testModifyLeadingWhiteSpace() { |
| assertTrue(false); |
| } |
| |
| public void testModifyTrailingWhiteSpace() { |
| assertTrue(false); |
| } |
| |
| public void testCovertBlockFromBraceToDoEnd() { |
| assertTrue(false); |
| } |
| |
| public void testConvertBlockFromDoEndToBrace() { |
| assertTrue(false); |
| } |
| |
| /////////////////////////////////////////////////////// |
| //Series of tests for removing various types of AST's |
| /////////////////////////////////////////////////////// |
| |
| /** |
| * Tests discovering and removing a class |
| */ |
| public void testRemoveClass() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering and removing a method def |
| */ |
| public void testRemoveMethodDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering and removing a block |
| */ |
| public void testRemoveBlock() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering and removing a statement |
| */ |
| public void testRemoveStatement() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering and removing a parameter from a method call |
| */ |
| public void testRemoveParameterFromMethodCall() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering and removing a parameter from a method def |
| */ |
| public void testRemoveParameterFromMethodDef() { |
| assertTrue(false); |
| } |
| |
| /** |
| * Tests discovering and removing a hash parameter from a method call |
| */ |
| public void testRemoveHashParameterFromMethodCall() { |
| assertTrue(false); |
| } |
| |
| //This assumes some way of resolving the formatted text from an AST |
| private void checkResults(ModuleDeclaration ast, String contents) { |
| assertTrue(false); |
| } |
| |
| private String loadContent(String path) throws IOException { |
| StringBuffer buffer = new StringBuffer(); |
| InputStream input = null; |
| try { |
| input = Activator.openResource(path); |
| InputStreamReader reader = new InputStreamReader(input); |
| |
| char[] cbuf = new char[1024 * 16]; |
| while (reader.ready() == true) { |
| int read = reader.read(cbuf); |
| buffer.append(cbuf, 0, read); |
| } |
| } |
| finally { |
| if (input != null) { |
| input.close(); |
| } |
| } |
| String content = buffer.toString(); |
| return content; |
| } |
| |
| } |