blob: 3820d1cee0f5f57a1612065e3625351579e4db19 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2016 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
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(name);
}
@Override
public void setUpSuite() throws Exception {
setUpScriptProject(SRC_PROJECT, Activator.PLUGIN_ID);
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() {
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();
try (InputStream 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);
}
}
String content = buffer.toString();
return content;
}
}