Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/AddVariableToDerivedDataTypeRefactoring.java325
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ExtractSubprogramToModuleRefactoring.java339
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/IntroduceCallTreeRefactoring.java196
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/MoveSubprogramToModuleRefactoring.java355
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/NestedIfThenElseToSelectCaseRefactoring.java248
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ReplaceDoLoopWithForallRefactoring.java147
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/TransformToDerivedDataTypeRefactoring.java304
-rw-r--r--org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/messages.properties2
-rw-r--r--org.eclipse.photran.ui.vpg/plugin.xml77
-rw-r--r--org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/AddVariableToDerivedDataTypeAction.java120
-rw-r--r--org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ExtractSubprogramToModuleAction.java100
-rw-r--r--org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/Messages.java14
-rw-r--r--org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/MoveSubprogramToModuleAction.java101
-rw-r--r--org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ReplaceDoLoopWithForallAction.java80
-rw-r--r--org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/TransformToDerivedDataTypeAction.java121
-rw-r--r--org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/messages.properties9
16 files changed, 2535 insertions, 3 deletions
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/AddVariableToDerivedDataTypeRefactoring.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/AddVariableToDerivedDataTypeRefactoring.java
new file mode 100644
index 00000000..b36088cd
--- /dev/null
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/AddVariableToDerivedDataTypeRefactoring.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.core.refactoring;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.photran.internal.core.analysis.binding.Definition;
+import org.eclipse.photran.internal.core.analysis.binding.ScopingNode;
+import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode;
+import org.eclipse.photran.internal.core.parser.ASTEntityDeclNode;
+import org.eclipse.photran.internal.core.parser.ASTObjectNameNode;
+import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode;
+import org.eclipse.photran.internal.core.parser.IASTListNode;
+import org.eclipse.photran.internal.core.parser.IASTNode;
+import org.eclipse.photran.internal.core.parser.IBodyConstruct;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring;
+import org.eclipse.photran.internal.core.vpg.PhotranTokenRef;
+
+/**
+ * Refactoring that adds a variable to a derived data type.
+ *
+ * @author Gustavo Risetti
+ */
+@SuppressWarnings("nls") // TODO: Externalize strings
+public class AddVariableToDerivedDataTypeRefactoring extends FortranEditorRefactoring {
+
+ private static final String OPS = "ops"; //$NON-NLS-1$
+
+ private LinkedList<IBodyConstruct> statements_nodes = new LinkedList<IBodyConstruct>();
+ private LinkedList<PhotranTokenRef> references = new LinkedList<PhotranTokenRef>();
+ private String derivedTypeName;
+ private String derivedTypeVariableName;
+ private PhotranTokenRef derived_data_type_ref = null;
+
+ @Override
+ public String getName() {
+ return "Add Variable To Derived Data Type";
+ }
+
+ public void setDerivedTypeVariableName(String name){
+ assert name != null;
+ derivedTypeVariableName = name;
+ }
+
+ public void setDerivedTypeName(String name){
+ assert name != null;
+ derivedTypeName = name;
+ }
+
+ // Search the beginning of variable declarations in each selected row, and checks
+ // if are used attributes that are not allowed in derived types.
+ private String findStatements(String s){
+ final String[] attributes_not_allowed = {"parameter", "intent", "target", "optional", "save", "external", "intrinsic"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+ final String[] types_allowed = {"integer", "real", "complex", "character", "logical"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ String statement_line = new String();
+ boolean has_type_in_line = false;
+ boolean init = false;
+ int j=0;
+ if(s.length() == 0){
+ return OPS;
+ }else{
+ for(int i = 0; i < s.length(); i++){
+ if(s.charAt(i) == ' ' || s.charAt(i) == '\t' && init == false){
+ j++;
+ }else{
+ init = true;
+ break;
+ }
+ }
+ if(s.charAt(j) == '!'){
+ return OPS;
+ }else{
+ statement_line = s.substring(j);
+ }
+ }
+ for(String type : types_allowed){
+ if(statement_line.toLowerCase().contains(type)){
+ has_type_in_line = true;
+ }
+ }
+ for(String attribute : attributes_not_allowed){
+ if(statement_line.toLowerCase().contains(attribute)){
+ has_type_in_line = false;
+ }
+ }
+ if(has_type_in_line){
+ return statement_line;
+ }else{
+ return OPS;
+ }
+ }
+
+ @Override
+ protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ final String SELECT_DECLARATION_WARNING = "Please select a variable declaration (or a list of variable declarations).";
+ final String USE_IN_DERIVED_TYPE_WARNING = "You can not use this refactoring within a Derived Data Type that already exists.";
+ ensureProjectHasRefactoringEnabled(status);
+ // Checks if variables were selected in a derived type that already exists.
+ IASTNode derived_type_node = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ ScopingNode derived_type_scope = ScopingNode.getEnclosingScope(derived_type_node);
+ if(derived_type_scope instanceof ASTDerivedTypeDefNode){
+ fail(USE_IN_DERIVED_TYPE_WARNING);
+ }
+ String selected_text = selectedRegionInEditor.getText();
+ if (selected_text.isEmpty()){
+ fail(SELECT_DECLARATION_WARNING);
+ }else{
+ String selected_lines[] = selected_text.split("\n");
+ for(String s : selected_lines){
+ s = findStatements(s);
+ if(!s.equalsIgnoreCase(OPS)){
+ statements_nodes.add(parseLiteralStatement(s));
+ }
+ }
+ LinkedList<IBodyConstruct> nodes_to_remove = new LinkedList<IBodyConstruct>();
+ for( IBodyConstruct node : statements_nodes){
+ if(!(node instanceof ASTTypeDeclarationStmtNode)){
+ nodes_to_remove.add(node);
+ }
+ }
+ // List of variables to be included in the derived type.
+ statements_nodes.removeAll(nodes_to_remove);
+ }
+ if(statements_nodes.isEmpty()){
+ fail(SELECT_DECLARATION_WARNING);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ final String VALID_NAMES_WARNING = "Fill in the fields with valid values.";
+ final String SPACE_TD_WARNING = "The name of the Derived Data Type can not contain spaces and exclamation points.";
+ final String SPACE_VTD_WARNING = "The name of the Derived Data Type instance can not contain spaces and exclamation points.";
+ final String NUMERIC_DIGITS_WARNING = "The names can not start with numeric digits.";
+ final String DERIVED_DATA_TYPE_REF_WARNING = "The Derived Data Type name entered was not found. Make sure you typed correctly.";
+ final String DERIVED_DATA_TYPE_INSTANCE_WARNING = "The Derived Data Type instance entered was not found. Make sure you typed correctly.";
+ final Character[] numeric_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+ boolean match_name = false;
+ if(derivedTypeName.length() < 1 || derivedTypeVariableName.length() < 1){
+ fail(VALID_NAMES_WARNING);
+ }
+ for(int i = 0; i< derivedTypeName.length(); i++){
+ if(derivedTypeName.charAt(i) == ' ' || derivedTypeName.charAt(i) == '!' || derivedTypeName.charAt(i) == '\t'){
+ fail(SPACE_TD_WARNING);
+ }
+ }
+ for(int i = 0; i< derivedTypeVariableName.length(); i++){
+ if(derivedTypeVariableName.charAt(i) == ' ' || derivedTypeVariableName.charAt(i) == '!' || derivedTypeVariableName.charAt(i) == '\t'){
+ fail(SPACE_VTD_WARNING);
+ }
+ }
+ for(int i=0; i<numeric_digits.length; i++){
+ if(derivedTypeName.charAt(0) == numeric_digits[i] || derivedTypeVariableName.charAt(0) == numeric_digits[i]){
+ fail(NUMERIC_DIGITS_WARNING);
+ }
+ }
+ // Checks if the derived type is spelled correctly.
+ IASTNode node = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ ScopingNode scope = ScopingNode.getEnclosingScope(node);
+ List<ScopingNode> contained_scopes = scope.getAllContainedScopes();
+ for(ScopingNode s : contained_scopes){
+ if(s instanceof ASTDerivedTypeDefNode){
+ if(((ASTDerivedTypeDefNode)s).getDerivedTypeStmt().getTypeName().getText().equalsIgnoreCase(derivedTypeName)){
+ derived_data_type_ref = ((ASTDerivedTypeDefNode)s).getRepresentativeToken();
+ }
+ }
+ }
+ if(derived_data_type_ref == null){
+ fail(DERIVED_DATA_TYPE_REF_WARNING);
+ }
+ // Checks if the instance name of the derived type is spelled correctly.
+ IASTListNode<IASTNode> body = (IASTListNode<IASTNode>)scope.getBody();
+ for(IASTNode n : body){
+ if(n instanceof ASTTypeDeclarationStmtNode){
+ if(((ASTTypeDeclarationStmtNode)n).getTypeSpec().isDerivedType()){
+ IASTListNode<ASTEntityDeclNode> entityDeclList = ((ASTTypeDeclarationStmtNode)n).getEntityDeclList();
+ for(ASTEntityDeclNode entity : entityDeclList){
+ if(entity.getObjectName().getObjectName().getText().equals(derivedTypeVariableName)){
+ match_name = true;
+ }
+ }
+ }
+ }
+ }
+ if(!match_name){
+ fail(DERIVED_DATA_TYPE_INSTANCE_WARNING);
+ }
+ }
+
+ @SuppressWarnings("static-access")
+ @Override
+ protected void doCreateChange(IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
+ List<Character> blank_characters = new LinkedList<Character>();
+ IASTNode node = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ ScopingNode scope = astOfFileInEditor.getRoot().getEnclosingScope(node);
+ String tab = ""; //$NON-NLS-1$
+ String headerStmt = scope.getHeaderStmt().toString();
+ String[] headerStmtWithoutComments = headerStmt.split("\n");
+ headerStmt = headerStmtWithoutComments[headerStmtWithoutComments.length - 1];
+ tab = getBlankCharacters(blank_characters, tab, headerStmt);
+ tab+="\t\t"; //$NON-NLS-1$
+ if(derived_data_type_ref != null){
+ String new_statements = derived_data_type_ref.findToken().getText()+"\n";
+ for(int i=0; i<statements_nodes.size(); i++){
+ IBodyConstruct stmt = statements_nodes.get(i);
+ new_statements += tab + ((ASTTypeDeclarationStmtNode)stmt).toString().trim();
+ if(i<statements_nodes.size()-1){
+ new_statements += "\n"; //$NON-NLS-1$
+ }
+ }
+ derived_data_type_ref.findToken().setText(new_statements);
+ }
+ // Search references of variables added to the derived type and replace the references by the derived type instance.
+ findReferences(scope);
+ if(statements_nodes.size() > 0){
+ addChangeFromModifiedAST(fileInEditor, progressMonitor);
+ }
+ vpg.releaseAST(fileInEditor);
+ }
+
+ void findReferences(ScopingNode scope){
+ List<Definition> used_definitions = new LinkedList<Definition>();
+ List<Definition> all_definitions = scope.getAllDefinitions();
+ LinkedList<String> node_names = new LinkedList<String>();
+ // Gets the names of the derived type variables.
+ for(IBodyConstruct t : statements_nodes){
+ IASTListNode<ASTEntityDeclNode> statements = ((ASTTypeDeclarationStmtNode)t).getEntityDeclList();
+ for(ASTEntityDeclNode d : statements){
+ node_names.add(d.getObjectName().toString().trim());
+ }
+ }
+ // Stores the definitions of variables actually used.
+ for(Definition def : all_definitions){
+ for(String n : node_names){
+ if(def.getDeclaredName().toString().trim().equals(n)){
+ used_definitions.add(def);
+ }
+ }
+ }
+ // Stores references to each definition actually used.
+ for(Definition d : used_definitions){
+ Set<PhotranTokenRef> references_to_definition = d.findAllReferences(false);
+ for(PhotranTokenRef t : references_to_definition){
+ references.add(t);
+ }
+ }
+ // Replaces references with the new type, with the access modifier %.
+ for(PhotranTokenRef t : references){
+ t.findToken().setText(derivedTypeVariableName+"%"+t.findToken().getText());
+ }
+ // Remove the declarations of variables that were included in the derived type.
+ for(Definition def : used_definitions){
+ try {
+ removeVariableDeclFor(def);
+ } catch (PreconditionFailure e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void removeVariableDeclFor(Definition def) throws PreconditionFailure {
+ ASTTypeDeclarationStmtNode declarationNode = getTypeDeclarationStmtNode(def.getTokenRef().findToken().getParent());
+ IASTListNode<ASTEntityDeclNode> entityDeclList = declarationNode.getEntityDeclList();
+ if (entityDeclList.size() == 1) {
+ declarationNode.findFirstToken().setWhiteBefore(""); //$NON-NLS-1$
+ declarationNode.replaceWith(""); //$NON-NLS-1$
+ }else {
+ removeVariableDeclFromList(def, entityDeclList);
+ }
+ }
+
+ private void removeVariableDeclFromList(Definition def, IASTListNode<ASTEntityDeclNode> entityDeclList) throws PreconditionFailure {
+ for (ASTEntityDeclNode decl : entityDeclList) {
+ ASTObjectNameNode objectName = decl.getObjectName();
+ String declName = objectName.getObjectName().getText();
+ if (declName.equals(def.getDeclaredName())) {
+ if (!entityDeclList.remove(decl)) {
+ fail("The operation could not be completed.");
+ }
+ break;
+ }
+ }
+ entityDeclList.findFirstToken().setWhiteBefore(" "); //$NON-NLS-1$
+ }
+
+ private ASTTypeDeclarationStmtNode getTypeDeclarationStmtNode(IASTNode node) {
+ if (node == null){
+ return null;
+ }else if (node instanceof ASTTypeDeclarationStmtNode){
+ return (ASTTypeDeclarationStmtNode)node;
+ }else{
+ return getTypeDeclarationStmtNode(node.getParent());
+ }
+ }
+
+ // Get indentation.
+ private String getBlankCharacters(List<Character> blank_characters, String tab, String headerStmt) {
+ boolean start = false;
+ for(int i=0; i<headerStmt.length(); i++){
+ char c = headerStmt.charAt(i);
+ if((c != '\t') && (c != ' ')){
+ start = true;
+ }
+ if((c == '\t' || c == ' ') && !start){
+ blank_characters.add(headerStmt.charAt(i));
+ }
+ }
+ for(int i=0; i<blank_characters.size();i++){
+ tab+=blank_characters.get(i);
+ }
+ return tab;
+ }
+}
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ExtractSubprogramToModuleRefactoring.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ExtractSubprogramToModuleRefactoring.java
new file mode 100644
index 00000000..9af70464
--- /dev/null
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ExtractSubprogramToModuleRefactoring.java
@@ -0,0 +1,339 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.core.refactoring;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.photran.internal.core.analysis.binding.Definition;
+import org.eclipse.photran.internal.core.analysis.binding.ScopingNode;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.parser.ASTAssignmentStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTCallStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode;
+import org.eclipse.photran.internal.core.parser.ASTEntityDeclNode;
+import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode;
+import org.eclipse.photran.internal.core.parser.ASTFunctionSubprogramNode;
+import org.eclipse.photran.internal.core.parser.ASTModuleNode;
+import org.eclipse.photran.internal.core.parser.ASTNameNode;
+import org.eclipse.photran.internal.core.parser.ASTObjectNameNode;
+import org.eclipse.photran.internal.core.parser.ASTSubroutineSubprogramNode;
+import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTUseStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTVarOrFnRefNode;
+import org.eclipse.photran.internal.core.parser.IASTListNode;
+import org.eclipse.photran.internal.core.parser.IASTNode;
+import org.eclipse.photran.internal.core.parser.IInternalSubprogram;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring;
+
+/**
+ * Refactoring that extracts a subprogram to a module.
+ *
+ * @author Gustavo Risetti
+ */
+@SuppressWarnings("nls") // TODO: Externalize strings
+public class ExtractSubprogramToModuleRefactoring extends FortranEditorRefactoring {
+
+ IASTNode selectedFunctionOrSubroutine = null;
+ List<ASTModuleNode> fileModules = new LinkedList<ASTModuleNode>();
+ private String moduleName;
+ ScopingNode originalScope = null;
+ List<Definition> parameters = new LinkedList<Definition>();
+
+ @Override
+ public String getName() {
+ return "Extract Subroutine Or Function To Module";
+ }
+
+ public void setModuleName(String name){
+ this.moduleName = name;
+ }
+
+ @Override
+ protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ ensureProjectHasRefactoringEnabled(status);
+ // Finds the selected node and checks if it is a subroutine or a function.
+ IASTNode selectedNode = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ if(selectedNode instanceof ASTSubroutineSubprogramNode || selectedNode instanceof ASTFunctionSubprogramNode){
+ selectedFunctionOrSubroutine = selectedNode;
+ }else{
+ fail("Please, select a Subroutine or a Function statement.");
+ }
+ // Stores all the modules of the file, to verify if the user will
+ // enter a name of an existing module.
+ for (ScopingNode scope : astOfFileInEditor.getRoot().getAllContainedScopes()){
+ if(scope instanceof ASTModuleNode){
+ fileModules.add((ASTModuleNode)scope);
+ }
+ }
+ // Stores a reference to the scope of where the subroutine or function will be extracted.
+ originalScope = ((ScopingNode)selectedFunctionOrSubroutine).getEnclosingScope();
+ }
+
+ ASTModuleNode moduleExists(String moduleName){
+ for(ASTModuleNode module : fileModules){
+ if(module.getName().equalsIgnoreCase(moduleName)){
+ return module;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ final String VALID_NAMES_WARNING = "Fill in the fields with valid values.";
+ final String SPACE_TD_WARNING = "The module name can not contain spaces and exclamation points.";
+ final String NUMERIC_DIGITS_WARNING = "The module name can not start with numeric digits.";
+ final Character[] numeric_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+
+ if(moduleName.length() < 1){
+ fail(VALID_NAMES_WARNING);
+ }
+ for(int i = 0; i< moduleName.length(); i++){
+ if(moduleName.charAt(i) == ' ' || moduleName.charAt(i) == '!' || moduleName.charAt(i) == '\t'){
+ fail(SPACE_TD_WARNING);
+ }
+ }
+ for(int i=0; i<numeric_digits.length; i++){
+ if(moduleName.charAt(0) == numeric_digits[i]){
+ fail(NUMERIC_DIGITS_WARNING);
+ }
+ }
+ ASTModuleNode module = moduleExists(moduleName);
+ if(module != null){
+ fail("The module " + moduleName.toUpperCase() + " already exists. Choose another name for the module to be created.");
+ }
+ }
+
+ @Override
+ protected void doCreateChange(IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
+ List<ScopingNode> scopes = new LinkedList<ScopingNode>();
+ // Located where the module will be added in the AST.
+ Token insertModule = astOfFileInEditor.getRoot().findFirstToken();
+ // Checks for a PARAMETER variable used only in the selected code.
+ boolean moveParameter;
+ for(Definition def : originalScope.getAllDefinitions()){
+ if(def.isParameter()){
+ if(!(hasReference(def.getDeclaredName(), originalScope)) && hasReference(def.getDeclaredName(), selectedFunctionOrSubroutine)){
+ moveParameter = true;
+ for(IInternalSubprogram internal : originalScope.getInternalSubprograms()){
+ if(internal instanceof ASTSubroutineSubprogramNode){
+ if(selectedFunctionOrSubroutine instanceof ASTSubroutineSubprogramNode){
+ if(((ASTSubroutineSubprogramNode)internal) != ((ASTSubroutineSubprogramNode)selectedFunctionOrSubroutine)){
+ if(hasReference(def.getDeclaredName(), ((ASTSubroutineSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }else{
+ if(hasReference(def.getDeclaredName(), ((ASTSubroutineSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }
+ if(internal instanceof ASTFunctionSubprogramNode){
+ if(selectedFunctionOrSubroutine instanceof ASTFunctionSubprogramNode){
+ if(((ASTFunctionSubprogramNode)internal) != ((ASTFunctionSubprogramNode)selectedFunctionOrSubroutine)){
+ if(hasReference(def.getDeclaredName(), ((ASTFunctionSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }else{
+ if(hasReference(def.getDeclaredName(), ((ASTFunctionSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }
+ }
+ if(moveParameter){
+ // If there is a parameter used only in the subroutine or function, it is stored
+ // in a list to be added in the module created.
+ parameters.add(def);
+ try{
+ // The original statement is removed from original scope.
+ removeVariableDeclFor(def);
+ }catch (PreconditionFailure e){
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ // Construction of the module.
+ String newModuleNode = "MODULE " + moduleName + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ // Adds parameters.
+ for(Definition def : parameters){
+ ASTTypeDeclarationStmtNode declarationNode = getTypeDeclarationStmtNode(def.getTokenRef().findToken().getParent());
+ newModuleNode += "\t" + declarationNode.toString(); //$NON-NLS-1$
+ }
+ newModuleNode+="CONTAINS\n"; //$NON-NLS-1$
+ // Adds the subroutine or function in the module body.
+ newModuleNode+=selectedFunctionOrSubroutine.toString();
+ newModuleNode+="END MODULE " + moduleName + "\n\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ insertModule.setText(newModuleNode + insertModule.getText());
+ // Adds the USE statement in scopes where the extracted subroutine or function is used.
+ addUseInScope(scopes);
+ selectedFunctionOrSubroutine.removeFromTree();
+ if(originalScope.getInternalSubprograms().size() == 1){
+ originalScope.getContainsStmt().removeFromTree();
+ }
+ addChangeFromModifiedAST(fileInEditor, progressMonitor);
+ vpg.releaseAST(fileInEditor);
+ }
+
+ private void removeVariableDeclFor(Definition def) throws PreconditionFailure {
+ ASTTypeDeclarationStmtNode declarationNode = getTypeDeclarationStmtNode(def.getTokenRef().findToken().getParent());
+ IASTListNode<ASTEntityDeclNode> entityDeclList = declarationNode.getEntityDeclList();
+ if (entityDeclList.size() == 1) {
+ declarationNode.findFirstToken().setWhiteBefore(""); //$NON-NLS-1$
+ declarationNode.replaceWith(""); //$NON-NLS-1$
+ }else {
+ removeVariableDeclFromList(def, entityDeclList);
+ }
+ }
+
+ private void removeVariableDeclFromList(Definition def, IASTListNode<ASTEntityDeclNode> entityDeclList) throws PreconditionFailure {
+ for (ASTEntityDeclNode decl : entityDeclList) {
+ ASTObjectNameNode objectName = decl.getObjectName();
+ String declName = objectName.getObjectName().getText();
+ if (declName.equals(def.getDeclaredName())) {
+ if (!entityDeclList.remove(decl)) {
+ fail("The operation could not be completed.");
+ }
+ break;
+ }
+ }
+ entityDeclList.findFirstToken().setWhiteBefore(" "); //$NON-NLS-1$
+ }
+
+ private ASTTypeDeclarationStmtNode getTypeDeclarationStmtNode(IASTNode node) {
+ if (node == null){
+ return null;
+ }else if (node instanceof ASTTypeDeclarationStmtNode){
+ return (ASTTypeDeclarationStmtNode)node;
+ }else{
+ return getTypeDeclarationStmtNode(node.getParent());
+ }
+ }
+
+ private boolean hasReference(String name, IASTNode scope){
+ boolean r = false;
+ if(scope instanceof ASTSubroutineSubprogramNode){
+ for (int i=0; i<((ASTSubroutineSubprogramNode)scope).getBody().size(); i++){
+ r = isReferenced(((ASTSubroutineSubprogramNode)scope).getBody().get(i), name);
+ if (r) break;
+ }
+ }
+ if(scope instanceof ASTFunctionSubprogramNode){
+ for (int i=0; i<((ASTFunctionSubprogramNode)scope).getBody().size(); i++){
+ r = isReferenced(((ASTFunctionSubprogramNode)scope).getBody().get(i), name);
+ if (r) break;
+ }
+ }
+ return r;
+ }
+
+ private boolean hasReference(String name, ScopingNode scope){
+ boolean r = false;
+ for (int i=0; i<scope.getBody().size(); i++){
+ r = isReferenced(scope.getBody().get(i), name);
+ if (r) break;
+ }
+ return r;
+ }
+
+ private boolean isReferenced(IASTNode node, String name){
+ boolean r = false;
+ if (node instanceof ASTVarOrFnRefNode) {
+ r = existsReferenceForVariable(node, name);
+ } else {
+ for (IASTNode child : node.getChildren()) {
+ if (! r ) {
+ r = isReferenced(child, name);
+ } else {
+ break;
+ }
+ }
+ }
+ return r;
+ }
+
+ private boolean existsReferenceForVariable(IASTNode node, String name){
+ boolean r = false;
+ if (node instanceof ASTNameNode) {
+ if ( ((ASTNameNode)node).getName().getText().equalsIgnoreCase(name) ) {
+ r = true;
+ }
+ } else {
+ for (IASTNode child : node.getChildren()) {
+ if (! r ) {
+ r = existsReferenceForVariable(child, name);
+ } else {
+ break;
+ }
+ }
+ }
+ return r;
+ }
+
+ private void addUseInScope(List<ScopingNode> scopes) {
+ String name = null;
+ for (ScopingNode scope : astOfFileInEditor.getRoot().getAllContainedScopes()){
+ if (!(scope instanceof ASTExecutableProgramNode) && !(scope instanceof ASTDerivedTypeDefNode)){
+ for(IASTNode node : scope.getBody()){
+ if(node instanceof ASTCallStmtNode){
+ if(selectedFunctionOrSubroutine instanceof ASTSubroutineSubprogramNode){
+ name = ((ASTSubroutineSubprogramNode)selectedFunctionOrSubroutine).getName();
+ }else{
+ name = ((ASTFunctionSubprogramNode)selectedFunctionOrSubroutine).getName();
+ }
+ if(((ASTCallStmtNode)node).getSubroutineName().getText().equalsIgnoreCase(name)){
+ if(!scopes.contains(scope)){
+ scopes.add(scope);
+ }
+ }
+ }if(node instanceof ASTAssignmentStmtNode){
+ if(selectedFunctionOrSubroutine instanceof ASTFunctionSubprogramNode){
+ name = ((ASTFunctionSubprogramNode)selectedFunctionOrSubroutine).getName();
+ String funcName = null;
+ if(((ASTAssignmentStmtNode)node).getRhs() instanceof ASTVarOrFnRefNode){
+ funcName = ((ASTVarOrFnRefNode)((ASTAssignmentStmtNode)node).getRhs()).getName().getName().getText();
+ if(name.equalsIgnoreCase(funcName)){
+ if(!scopes.contains(scope)){
+ scopes.add(scope);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ boolean hasUse = false;
+ for(ScopingNode scope : scopes){
+ hasUse = false;
+ for(IASTNode node : scope.getBody()){
+ if(node instanceof ASTUseStmtNode){
+ if(((ASTUseStmtNode)node).getName().getText().equalsIgnoreCase(moduleName)){
+ hasUse = true;
+ break;
+ }
+ }
+ }
+ if(!hasUse){
+ String lastToken = scope.getHeaderStmt().findLastToken().getText();
+ scope.getHeaderStmt().findLastToken().setText(lastToken+"\tUSE " + moduleName + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+}
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/IntroduceCallTreeRefactoring.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/IntroduceCallTreeRefactoring.java
new file mode 100644
index 00000000..c50979cd
--- /dev/null
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/IntroduceCallTreeRefactoring.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.core.refactoring;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.photran.core.IFortranAST;
+import org.eclipse.photran.internal.core.analysis.binding.ScopingNode;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.parser.ASTCallStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode;
+import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode;
+import org.eclipse.photran.internal.core.parser.ASTMainProgramNode;
+import org.eclipse.photran.internal.core.parser.IASTListNode;
+import org.eclipse.photran.internal.core.parser.IASTNode;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranResourceRefactoring;
+
+/**
+ * Refactoring that adds a call tree in a comment preceding each subprogram.
+ *
+ * @author Gustavo Risetti
+ */
+//@SuppressWarnings("nls") // TODO: Externalize strings
+public class IntroduceCallTreeRefactoring extends FortranResourceRefactoring {
+ @Override
+ protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ try {
+ for (IFile file : selectedFiles) {
+ IFortranAST ast = vpg.acquirePermanentAST(file);
+ if (ast == null) {
+ status.addError("One of the selected files (" + file.getName() +") cannot be parsed.");
+ } else {
+ makeChangesTo(file, ast, status, pm);
+ vpg.releaseAST(file);
+ }
+ }
+ } finally {
+ vpg.releaseAllASTs();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void makeChangesTo(IFile file, IFortranAST ast, RefactoringStatus status, IProgressMonitor pm) {
+ List<ScopingNode> scopes = ast.getRoot().getAllContainedScopes();
+ List<Character> blank_characters = new LinkedList<Character>();
+ List<String> callStmtsOfScope = new LinkedList<String>();
+ Integer line_int = new Integer(0);
+ ScopingNode scopeChanged = null;
+ boolean hasCall = false;
+ // Get the number of calls within the main program
+ int mainProgramCalls = getMainProgramCalls(scopes);
+ int scopeCalls = 0;
+ for (ScopingNode scope : scopes){
+ // Updates number of calls in scope.
+ scopeCalls = getScopeCalls(scopeCalls, scope);
+ callStmtsOfScope.clear();
+ blank_characters.clear();
+ scopeChanged = null;
+ hasCall = false;
+ if (!(scope instanceof ASTExecutableProgramNode) && !(scope instanceof ASTDerivedTypeDefNode)){
+ IASTListNode<IASTNode> body = (IASTListNode<IASTNode>)scope.getBody();
+ for (IASTNode node : body){
+ if (node instanceof ASTCallStmtNode){
+ hasCall = true;
+ scopeChanged = scope;
+ // Information of the line number where are the call.
+ if(scope instanceof ASTMainProgramNode){
+ line_int = node.findFirstToken().getLine() + mainProgramCalls;
+ }else{
+ line_int = node.findFirstToken().getLine() + scopeCalls + mainProgramCalls;
+ }
+ String line = line_int.toString();
+ // Adds entry to the calls buffer of the scope.
+ callStmtsOfScope.add(((ASTCallStmtNode)node).getSubroutineName().getText() + " (on line <" +line+">)");
+ }
+ }
+ if((hasCall== true) && (scopeChanged != null)){
+ // Get the declaration of the subprogram.
+ Token firstToken = scopeChanged.findFirstToken();
+ String firstTokenText = firstToken.getText();
+ // Get indentation
+ String tab = ""; //$NON-NLS-1$
+ String headerStmt = scopeChanged.getHeaderStmt().toString();
+ String[] headerStmtWithoutComments = headerStmt.split("\n"); //$NON-NLS-1$
+ headerStmt = headerStmtWithoutComments[headerStmtWithoutComments.length - 1];
+ tab = getBlankCharacters(blank_characters, tab, headerStmt);
+ String name = ""; //$NON-NLS-1$
+ if(scopeChanged.isMainProgram()){
+ name = " in program ";
+ }if(scopeChanged.isModule()){
+ name = " in module ";
+ }if(scopeChanged.isSubprogram()){
+ name = " in subroutine ";
+ }
+ // Prints the call tree of each subroutine.
+ firstToken.setText("! " + "Calls" + name + scopeChanged.getName().toUpperCase()+": \n"); //$NON-NLS-1$
+ for(int i=0; i<callStmtsOfScope.size(); i++){
+ String arrow = "="; //$NON-NLS-1$
+ for(int j=0; j<i; j++){
+ arrow += "="; //$NON-NLS-1$
+ }
+ arrow += ">"; //$NON-NLS-1$
+ firstToken.setText(firstToken.getText()+ tab + "! " + arrow + " " + callStmtsOfScope.get(i).toString() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ firstToken.setText(firstToken.getText()+tab + firstTokenText.trim());
+ }
+ }
+ }
+ addChangeFromModifiedAST(file, pm);
+ }
+
+ // Get correct indentation.
+ private String getBlankCharacters(List<Character> blank_characters, String tab, String headerStmt) {
+ boolean start = false;
+ for(int i=0; i<headerStmt.length(); i++){
+ char c = headerStmt.charAt(i);
+ if((c != '\t') && (c != ' ')){
+ start = true;
+ }
+ if((c == '\t' || c == ' ') && !start){
+ blank_characters.add(headerStmt.charAt(i));
+ }
+ }
+ for(int i=0; i<blank_characters.size();i++){
+ tab+=blank_characters.get(i);
+ }
+ return tab;
+ }
+
+ // Get the calls of the scope.
+ @SuppressWarnings("unchecked")
+ private int getScopeCalls(int scopeCalls, ScopingNode scope) {
+ if (!(scope instanceof ASTExecutableProgramNode) && !(scope instanceof ASTDerivedTypeDefNode)){
+ IASTListNode<IASTNode> body = (IASTListNode<IASTNode>)scope.getBody();
+ int n = 0;
+ for (IASTNode node : body){
+ if (node instanceof ASTCallStmtNode){
+ n++;
+ }
+ }
+ if(n > 0){
+ n++;
+ }
+ scopeCalls+=n;
+ }
+ return scopeCalls;
+ }
+
+ // Get the calls of the main program.
+ @SuppressWarnings("unchecked")
+ private int getMainProgramCalls(List<ScopingNode> scopes){
+ int mainProgramCalls = 0;
+ for (ScopingNode scope : scopes){
+ if(scope instanceof ASTMainProgramNode){
+ IASTListNode<IASTNode> body = (IASTListNode<IASTNode>)scope.getBody();
+ for (IASTNode node : body){
+ if (node instanceof ASTCallStmtNode){
+ mainProgramCalls ++;
+ }
+ }
+ if(mainProgramCalls > 0){
+ mainProgramCalls ++;
+ }
+ }
+ }
+ return mainProgramCalls;
+ }
+
+ @Override
+ protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ ensureProjectHasRefactoringEnabled(status);
+ removeFixedFormFilesFrom(this.selectedFiles, status);
+ removeCpreprocessedFilesFrom(this.selectedFiles, status);
+ }
+
+ @Override
+ protected void doCreateChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
+ // The change is made in method makeChangesTo(...).
+ }
+
+ @Override
+ public String getName() {
+ return "Introduce Call Tree";
+ }
+}
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/MoveSubprogramToModuleRefactoring.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/MoveSubprogramToModuleRefactoring.java
new file mode 100644
index 00000000..14354807
--- /dev/null
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/MoveSubprogramToModuleRefactoring.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.core.refactoring;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.photran.internal.core.analysis.binding.Definition;
+import org.eclipse.photran.internal.core.analysis.binding.ScopingNode;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.parser.ASTAssignmentStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTCallStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTContainsStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode;
+import org.eclipse.photran.internal.core.parser.ASTEntityDeclNode;
+import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode;
+import org.eclipse.photran.internal.core.parser.ASTFunctionSubprogramNode;
+import org.eclipse.photran.internal.core.parser.ASTImplicitStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTModuleNode;
+import org.eclipse.photran.internal.core.parser.ASTNameNode;
+import org.eclipse.photran.internal.core.parser.ASTObjectNameNode;
+import org.eclipse.photran.internal.core.parser.ASTSubroutineSubprogramNode;
+import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTUseStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTVarOrFnRefNode;
+import org.eclipse.photran.internal.core.parser.IASTListNode;
+import org.eclipse.photran.internal.core.parser.IASTNode;
+import org.eclipse.photran.internal.core.parser.IInternalSubprogram;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring;
+
+/**
+ * Refactoring that moves a subprogram into a module.
+ *
+ * @author Gustavo Risetti
+ */
+@SuppressWarnings("nls") // TODO: Externalize strings
+public class MoveSubprogramToModuleRefactoring extends FortranEditorRefactoring {
+
+ IASTNode selectedFunctionOrSubroutine = null;
+ List<ASTModuleNode> fileModules = new LinkedList<ASTModuleNode>();
+ private String moduleName;
+ ScopingNode originalScope = null;
+ ASTModuleNode module = null;
+ List<Definition> parameters = new LinkedList<Definition>();
+
+ @Override
+ public String getName() {
+ return "Move Subroutine Or Function To Module";
+ }
+
+ public void setModuleName(String name){
+ this.moduleName = name;
+ }
+
+ @Override
+ protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ ensureProjectHasRefactoringEnabled(status);
+ // Finds the selected node and checks if it is a subroutine or a function.
+ IASTNode selectedNode = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ if(selectedNode instanceof ASTSubroutineSubprogramNode || selectedNode instanceof ASTFunctionSubprogramNode){
+ selectedFunctionOrSubroutine = selectedNode;
+ }else{
+ fail("Please, select a Subroutine or a Function statement.");
+ }
+ // Stores all the modules of the file, to verify if the user will
+ // enter a name of an existing module.
+ for (ScopingNode scope : astOfFileInEditor.getRoot().getAllContainedScopes()){
+ if(scope instanceof ASTModuleNode){
+ fileModules.add((ASTModuleNode)scope);
+ }
+ }
+ // Stores a reference to the scope of where the subroutine or function will be moved.
+ originalScope = ((ScopingNode)selectedFunctionOrSubroutine).getEnclosingScope();
+ }
+
+ ASTModuleNode moduleExists(String moduleName){
+ for(ASTModuleNode module : fileModules){
+ if(module.getName().equalsIgnoreCase(moduleName)){
+ return module;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ final String VALID_NAMES_WARNING = "Fill in the fields with valid values.";
+ final String SPACE_TD_WARNING = "The module name can not contain spaces and exclamation points.";
+ final String NUMERIC_DIGITS_WARNING = "The module name can not start with numeric digits.";
+ final Character[] numeric_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+
+ if(moduleName.length() < 1){
+ fail(VALID_NAMES_WARNING);
+ }
+ for(int i = 0; i< moduleName.length(); i++){
+ if(moduleName.charAt(i) == ' ' || moduleName.charAt(i) == '!' || moduleName.charAt(i) == '\t'){
+ fail(SPACE_TD_WARNING);
+ }
+ }
+ for(int i=0; i<numeric_digits.length; i++){
+ if(moduleName.charAt(0) == numeric_digits[i]){
+ fail(NUMERIC_DIGITS_WARNING);
+ }
+ }
+ module = moduleExists(moduleName);
+ if(module == null){
+ fail("The module " + moduleName.toUpperCase() + " does not exist. Make sure you typed the name correctly.");
+ }
+ }
+
+ @Override
+ protected void doCreateChange(IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
+ List<ScopingNode> scopes = new LinkedList<ScopingNode>();
+ // Checks for a PARAMETER variable used only in the selected code.
+ boolean moveParameter;
+ for(Definition def : originalScope.getAllDefinitions()){
+ if(def.isParameter()){
+ if(!(hasReference(def.getDeclaredName(), originalScope)) && hasReference(def.getDeclaredName(), selectedFunctionOrSubroutine)){
+ moveParameter = true;
+ for(IInternalSubprogram internal : originalScope.getInternalSubprograms()){
+ if(internal instanceof ASTSubroutineSubprogramNode){
+ if(selectedFunctionOrSubroutine instanceof ASTSubroutineSubprogramNode){
+ if(((ASTSubroutineSubprogramNode)internal) != ((ASTSubroutineSubprogramNode)selectedFunctionOrSubroutine)){
+ if(hasReference(def.getDeclaredName(), ((ASTSubroutineSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }else{
+ if(hasReference(def.getDeclaredName(), ((ASTSubroutineSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }
+ if(internal instanceof ASTFunctionSubprogramNode){
+ if(selectedFunctionOrSubroutine instanceof ASTFunctionSubprogramNode){
+ if(((ASTFunctionSubprogramNode)internal) != ((ASTFunctionSubprogramNode)selectedFunctionOrSubroutine)){
+ if(hasReference(def.getDeclaredName(), ((ASTFunctionSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }else{
+ if(hasReference(def.getDeclaredName(), ((ASTFunctionSubprogramNode)internal))){
+ moveParameter = false;
+ }
+ }
+ }
+ }
+ if(moveParameter){
+ parameters.add(def);
+ try{
+ removeVariableDeclFor(def);
+ }catch (PreconditionFailure e){
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ Token insertParameters = null;
+ for(IASTNode node : module.getModuleBody()){
+ if(node instanceof ASTImplicitStmtNode){
+ insertParameters = ((ASTImplicitStmtNode)node).findLastToken();
+ break;
+ }
+ }
+ String parametersString = ""; //$NON-NLS-1$
+ for(Definition def : parameters){
+ ASTTypeDeclarationStmtNode declarationNode = getTypeDeclarationStmtNode(def.getTokenRef().findToken().getParent());
+ parametersString += "\t" + declarationNode.toString(); //$NON-NLS-1$
+ }
+ if(!parameters.isEmpty()){
+ if(insertParameters != null){
+ insertParameters.setText(insertParameters.getText() +"\n"+ parametersString); //$NON-NLS-1$
+ }else{
+ insertParameters = module.getNameToken();
+ insertParameters.setText(insertParameters.getText() +"\n"+ parametersString); //$NON-NLS-1$
+ }
+ }
+
+ ASTContainsStmtNode contains = module.getContainsStmt();
+ // Checks if the module has the CONTAINS command.
+ if(contains != null){
+ String tokenText = contains.findLastToken().getText();
+ contains.findLastToken().setText(tokenText + selectedFunctionOrSubroutine.toString());
+ }else{
+ String tokenText = module.getEndModuleStmt().findFirstToken().getText();
+ module.getEndModuleStmt().findFirstToken().setText("CONTAINS\n"+selectedFunctionOrSubroutine.toString()+tokenText); //$NON-NLS-1$
+ }
+ // Adds the USE statement in scopes where the moved subroutine or function is used.
+ addUseInScope(scopes);
+ selectedFunctionOrSubroutine.removeFromTree();
+ if(originalScope.getInternalSubprograms().size() == 1){
+ originalScope.getContainsStmt().removeFromTree();
+ }
+ addChangeFromModifiedAST(fileInEditor, progressMonitor);
+ vpg.releaseAST(fileInEditor);
+ }
+
+ private void removeVariableDeclFor(Definition def) throws PreconditionFailure {
+ ASTTypeDeclarationStmtNode declarationNode = getTypeDeclarationStmtNode(def.getTokenRef().findToken().getParent());
+ IASTListNode<ASTEntityDeclNode> entityDeclList = declarationNode.getEntityDeclList();
+ if (entityDeclList.size() == 1) {
+ declarationNode.findFirstToken().setWhiteBefore(""); //$NON-NLS-1$
+ declarationNode.replaceWith(""); //$NON-NLS-1$
+ }else {
+ removeVariableDeclFromList(def, entityDeclList);
+ }
+ }
+
+ private void removeVariableDeclFromList(Definition def, IASTListNode<ASTEntityDeclNode> entityDeclList) throws PreconditionFailure {
+ for (ASTEntityDeclNode decl : entityDeclList) {
+ ASTObjectNameNode objectName = decl.getObjectName();
+ String declName = objectName.getObjectName().getText();
+ if (declName.equals(def.getDeclaredName())) {
+ if (!entityDeclList.remove(decl)) {
+ fail("The operation could not be completed.");
+ }
+ break;
+ }
+ }
+ entityDeclList.findFirstToken().setWhiteBefore(" "); //$NON-NLS-1$
+ }
+
+ private ASTTypeDeclarationStmtNode getTypeDeclarationStmtNode(IASTNode node) {
+ if (node == null){
+ return null;
+ }else if (node instanceof ASTTypeDeclarationStmtNode){
+ return (ASTTypeDeclarationStmtNode)node;
+ }else{
+ return getTypeDeclarationStmtNode(node.getParent());
+ }
+ }
+
+ private boolean hasReference(String name, IASTNode scope){
+ boolean r = false;
+ if(scope instanceof ASTSubroutineSubprogramNode){
+ for (int i=0; i<((ASTSubroutineSubprogramNode)scope).getBody().size(); i++){
+ r = isReferenced(((ASTSubroutineSubprogramNode)scope).getBody().get(i), name);
+ if (r) break;
+ }
+ }
+ if(scope instanceof ASTFunctionSubprogramNode){
+ for (int i=0; i<((ASTFunctionSubprogramNode)scope).getBody().size(); i++){
+ r = isReferenced(((ASTFunctionSubprogramNode)scope).getBody().get(i), name);
+ if (r) break;
+ }
+ }
+ return r;
+ }
+
+ private boolean hasReference(String name, ScopingNode scope){
+ boolean r = false;
+ for (int i=0; i<scope.getBody().size(); i++){
+ r = isReferenced(scope.getBody().get(i), name);
+ if (r) break;
+ }
+ return r;
+ }
+
+ private boolean isReferenced(IASTNode node, String name){
+ boolean r = false;
+ if (node instanceof ASTVarOrFnRefNode) {
+ r = existsReferenceForVariable(node, name);
+ } else {
+ for (IASTNode child : node.getChildren()) {
+ if (! r ) {
+ r = isReferenced(child, name);
+ } else {
+ break;
+ }
+ }
+ }
+ return r;
+ }
+
+ private boolean existsReferenceForVariable(IASTNode node, String name){
+ boolean r = false;
+ if (node instanceof ASTNameNode) {
+ if ( ((ASTNameNode)node).getName().getText().equalsIgnoreCase(name) ) {
+ r = true;
+ }
+ } else {
+ for (IASTNode child : node.getChildren()) {
+ if (! r ) {
+ r = existsReferenceForVariable(child, name);
+ } else {
+ break;
+ }
+ }
+ }
+ return r;
+ }
+
+ private void addUseInScope(List<ScopingNode> scopes) {
+ String name = null;
+ for (ScopingNode scope : astOfFileInEditor.getRoot().getAllContainedScopes()){
+ if (!(scope instanceof ASTExecutableProgramNode) && !(scope instanceof ASTDerivedTypeDefNode)){
+ for(IASTNode node : scope.getBody()){
+ if(node instanceof ASTCallStmtNode){
+ if(selectedFunctionOrSubroutine instanceof ASTSubroutineSubprogramNode){
+ name = ((ASTSubroutineSubprogramNode)selectedFunctionOrSubroutine).getName();
+ }else{
+ name = ((ASTFunctionSubprogramNode)selectedFunctionOrSubroutine).getName();
+ }
+ if(((ASTCallStmtNode)node).getSubroutineName().getText().equalsIgnoreCase(name)){
+ if(!scopes.contains(scope)){
+ scopes.add(scope);
+ }
+ }
+ }if(node instanceof ASTAssignmentStmtNode){
+ if(selectedFunctionOrSubroutine instanceof ASTFunctionSubprogramNode){
+ name = ((ASTFunctionSubprogramNode)selectedFunctionOrSubroutine).getName();
+ String funcName = null;
+ if(((ASTAssignmentStmtNode)node).getRhs() instanceof ASTVarOrFnRefNode){
+ funcName = ((ASTVarOrFnRefNode)((ASTAssignmentStmtNode)node).getRhs()).getName().getName().getText();
+ if(name.equalsIgnoreCase(funcName)){
+ if(!scopes.contains(scope)){
+ scopes.add(scope);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ boolean hasUse = false;
+ for(ScopingNode scope : scopes){
+ hasUse = false;
+ for(IASTNode node : scope.getBody()){
+ if(node instanceof ASTUseStmtNode){
+ if(((ASTUseStmtNode)node).getName().getText().equalsIgnoreCase(moduleName)){
+ hasUse = true;
+ break;
+ }
+ }
+ }
+ if(!hasUse){
+ String lastToken = scope.getHeaderStmt().findLastToken().getText();
+ scope.getHeaderStmt().findLastToken().setText(lastToken+"\tUSE " + moduleName + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+}
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/NestedIfThenElseToSelectCaseRefactoring.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/NestedIfThenElseToSelectCaseRefactoring.java
new file mode 100644
index 00000000..4aaf1304
--- /dev/null
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/NestedIfThenElseToSelectCaseRefactoring.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.core.refactoring;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.photran.core.IFortranAST;
+import org.eclipse.photran.internal.core.analysis.binding.ScopingNode;
+import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode;
+import org.eclipse.photran.internal.core.parser.ASTElseConstructNode;
+import org.eclipse.photran.internal.core.parser.ASTElseIfConstructNode;
+import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode;
+import org.eclipse.photran.internal.core.parser.ASTIfConstructNode;
+import org.eclipse.photran.internal.core.parser.IASTListNode;
+import org.eclipse.photran.internal.core.parser.IASTNode;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranResourceRefactoring;
+
+/**
+ * Refactoring that converts nested if/then/else constructs into a SELECT CASE construct.
+ *
+ * @author Gustavo Risetti
+ */
+@SuppressWarnings("nls") // TODO: Externalize strings
+public class NestedIfThenElseToSelectCaseRefactoring extends FortranResourceRefactoring{
+
+ List<ASTIfConstructNode> ifNodes = new LinkedList<ASTIfConstructNode>();
+ List<ASTIfConstructNode> removeIfNodes = new LinkedList<ASTIfConstructNode>();
+ List<String> varNames = new LinkedList<String>();
+ List<String> cases = new LinkedList<String>();
+ List<String> bodyCases = new LinkedList<String>();
+
+ @Override
+ public String getName() {
+ return "Nested If-Then-Else To Select Case";
+ }
+
+ @Override
+ protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ ensureProjectHasRefactoringEnabled(status);
+ removeFixedFormFilesFrom(this.selectedFiles, status);
+ removeCpreprocessedFilesFrom(this.selectedFiles, status);
+ }
+
+ @Override
+ protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure{
+ try {
+ for (IFile file : selectedFiles) {
+ IFortranAST ast = vpg.acquirePermanentAST(file);
+ if(ast == null) {
+ status.addError("One of the selected files (" + file.getName() +") cannot be parsed.");
+ }else {
+ makeChangesTo(file, ast, status, pm);
+ vpg.releaseAST(file);
+ }
+ }
+ }finally {
+ vpg.releaseAllASTs();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void makeChangesTo(IFile file, IFortranAST ast, RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ boolean hasChanged = false;
+ List<ScopingNode> scopes = ast.getRoot().getAllContainedScopes();
+ for(ScopingNode scope : scopes){
+ if (!(scope instanceof ASTExecutableProgramNode) && !(scope instanceof ASTDerivedTypeDefNode)){
+ IASTListNode<IASTNode> body = (IASTListNode<IASTNode>)scope.getBody();
+ // Find nodes which contains nested if-then-else and add in a node list.
+ for(IASTNode node : body){
+ if(node instanceof ASTIfConstructNode){
+ ASTIfConstructNode ifNode = ((ASTIfConstructNode)node);
+ if(ifNode.getElseIfConstruct() != null){
+ ifNodes.add((ASTIfConstructNode)node);
+ }
+ }
+ }
+ }
+ }
+ // Checks that appear only allowed comparisons (==, .eq., or)
+ for(ASTIfConstructNode ifNode : ifNodes){
+ parserStmts(ifNode, null);
+ }
+ // Remove the nodes that do not satisfy the condition to be a case of a SELECT CASE
+ ifNodes.removeAll(removeIfNodes);
+ for(ASTIfConstructNode ifNode : ifNodes){
+ // Gets the list of values and cases for the new node to be built.
+ getPairs(ifNode, null);
+ // Checks if the same variable is evaluated in expressions.
+ if(hasSameVars()){
+ hasChanged = true;
+ String[] tabWithComments = ifNode.findFirstToken().getWhiteBefore().toString().split("\n"); //$NON-NLS-1$
+ String tab = tabWithComments[tabWithComments.length-1];
+ for(int i = 0; i < tab.length(); i ++){
+ if(tab.charAt(i) == ' ' || tab.charAt(i) == '\t'){
+ continue;
+ }else{
+ tab = ""; //$NON-NLS-1$
+ break;
+ }
+ }
+ // The new node is constructed.
+ String selectCaseNode = "SELECT CASE (" + varNames.get(0).trim() + ")\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ for(int i = 0; i< cases.size(); i++){
+ String casesUnits = tab + "\tCASE " + cases.get(i).trim() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ String[] body = bodyCases.get(i).split("\n"); //$NON-NLS-1$
+ for(String bodyLine : body){
+ casesUnits += tab + "\t\t" + bodyLine.trim()+"\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ selectCaseNode += casesUnits;
+ }
+ selectCaseNode += tab + "END SELECT\n"; //$NON-NLS-1$
+ // Replaces the old node with the new node in AST.
+ ifNode.replaceWith(selectCaseNode);
+ varNames.clear();
+ cases.clear();
+ bodyCases.clear();
+ }else{
+ varNames.clear();
+ cases.clear();
+ bodyCases.clear();
+ }
+ }
+ if (hasChanged){
+ addChangeFromModifiedAST(file, pm);
+ }
+ }
+
+ // Checks if the same variable is evaluated in expressions.
+ private boolean hasSameVars(){
+ for(int i=0; i<varNames.size()-1; i++){
+ if(!(varNames.get(i).equalsIgnoreCase(varNames.get(i+1)))){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Gets the list of values ​​and cases.
+ private void getPairs(ASTIfConstructNode ifNode, ASTElseIfConstructNode elseIfNode) {
+ if(elseIfNode == null){
+ String ifExpression = ifNode.getIfThenStmt().getGuardingExpression().toString().trim();
+ ifExpression = ifExpression.replaceAll(".OR.", ".or."); //$NON-NLS-1$ //$NON-NLS-2$
+ ifExpression = ifExpression.replaceAll(".Or.", ".or."); //$NON-NLS-1$ //$NON-NLS-2$
+ ifExpression = ifExpression.replaceAll(".oR.", ".or."); //$NON-NLS-1$ //$NON-NLS-2$
+ ifExpression = ifExpression.replaceAll(".EQ.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ ifExpression = ifExpression.replaceAll(".Eq.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ ifExpression = ifExpression.replaceAll(".eQ.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ ifExpression = ifExpression.replaceAll(".eq.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ String[] orSplit = ifExpression.split(".or."); //$NON-NLS-1$
+ for(String s : orSplit){
+ s = s.trim();
+ String[] eqSplit = s.split("=="); //$NON-NLS-1$
+ for(String seq : eqSplit){
+ seq = seq.trim();
+ }
+ for(int i=0; i<eqSplit.length; i+=2){
+ varNames.add(eqSplit[i]);
+ cases.add("("+eqSplit[i+1].trim()+")"); //$NON-NLS-1$ //$NON-NLS-2$
+ bodyCases.add(ifNode.getConditionalBody().toString());
+ }
+ }
+ ASTElseIfConstructNode elseIf = ifNode.getElseIfConstruct();
+ if(elseIf != null){
+ getPairs(ifNode, elseIf);
+ }
+ }else{
+ String elseIfExpression = elseIfNode.getElseIfStmt().getGuardingExpression().toString().trim();
+ elseIfExpression = elseIfExpression.replaceAll(".OR.", ".or."); //$NON-NLS-1$ //$NON-NLS-2$
+ elseIfExpression = elseIfExpression.replaceAll(".Or.", ".or."); //$NON-NLS-1$ //$NON-NLS-2$
+ elseIfExpression = elseIfExpression.replaceAll(".oR.", ".or."); //$NON-NLS-1$ //$NON-NLS-2$
+ elseIfExpression = elseIfExpression.replaceAll(".EQ.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ elseIfExpression = elseIfExpression.replaceAll(".Eq.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ elseIfExpression = elseIfExpression.replaceAll(".eQ.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ elseIfExpression = elseIfExpression.replaceAll(".eq.", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+ String[] orSplit = elseIfExpression.split(".or."); //$NON-NLS-1$
+ for(String s : orSplit){
+ s = s.trim();
+ String[] eqSplit = s.split("=="); //$NON-NLS-1$
+ for(String seq : eqSplit){
+ seq = seq.trim();
+ }
+ for(int i=0; i<eqSplit.length; i+=2){
+ varNames.add(eqSplit[i]);
+ cases.add("("+eqSplit[i+1].trim()+")"); //$NON-NLS-1$ //$NON-NLS-2$
+ bodyCases.add(elseIfNode.getConditionalBody().toString());
+ }
+ }
+ ASTElseIfConstructNode elseIf = elseIfNode.getElseIfConstruct();
+ if(elseIf != null){
+ getPairs(ifNode, elseIf);
+ }else{
+ ASTElseConstructNode elseDefault = elseIfNode.getElseConstruct();
+ if(elseDefault != null){
+ String elseDefaultExpression = elseDefault.getConditionalBody().toString();
+ cases.add("DEFAULT"); //$NON-NLS-1$
+ bodyCases.add(elseDefaultExpression);
+ }
+ }
+ }
+ }
+
+ // Checks that appear only allowed comparisons (==, .eq., or)
+ private void parserStmts(ASTIfConstructNode ifNode, ASTElseIfConstructNode elseIfNode) {
+ String not_aloowed[] = {">", ".GT.", "<", ".LT.", ">=", ".GE.", "<=", ".LE.", "/=", ".NE.", ".AND.", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$
+ ".EQV.", ".NEQV.", ".gt.", ".lt.", ".ge.", ".le.", ".ne.", ".and.", ".eqv.", ".neqv."}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$
+ if(elseIfNode == null){
+ String ifExpression = ifNode.getIfThenStmt().getGuardingExpression().toString().trim();
+ for(String s : not_aloowed){
+ if(ifExpression.contains(s)){
+ removeIfNodes.add(ifNode);
+ return;
+ }
+ }
+ ASTElseIfConstructNode elseIf = ifNode.getElseIfConstruct();
+ if(elseIf != null){
+ parserStmts(ifNode, elseIf);
+ }
+ }else{
+ String elseIfExpression = elseIfNode.getElseIfStmt().getGuardingExpression().toString().trim();
+ for(String s : not_aloowed){
+ if(elseIfExpression.contains(s)){
+ removeIfNodes.add(ifNode);
+ return;
+ }
+ }
+ ASTElseIfConstructNode elseIf = elseIfNode.getElseIfConstruct();
+ if(elseIf != null){
+ parserStmts(ifNode, elseIf);
+ }
+ }
+ }
+
+ @Override
+ protected void doCreateChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
+ // The change is made in method makeChangesTo(...).
+ }
+}
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ReplaceDoLoopWithForallRefactoring.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ReplaceDoLoopWithForallRefactoring.java
new file mode 100644
index 00000000..4753ad56
--- /dev/null
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/ReplaceDoLoopWithForallRefactoring.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.core.refactoring;
+
+import java.util.LinkedList;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.photran.internal.core.analysis.loops.ASTProperLoopConstructNode;
+import org.eclipse.photran.internal.core.analysis.loops.LoopReplacer;
+import org.eclipse.photran.internal.core.parser.ASTAssignmentStmtNode;
+import org.eclipse.photran.internal.core.parser.IASTListNode;
+import org.eclipse.photran.internal.core.parser.IASTNode;
+import org.eclipse.photran.internal.core.parser.IExecutionPartConstruct;
+import org.eclipse.photran.internal.core.parser.IExpr;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring;
+
+/**
+ * Refactoring that replaces a DO loop with a FORALL loop.
+ *
+ * @author Gustavo Risetti
+ */
+@SuppressWarnings("nls") // TODO: Externalize strings
+public class ReplaceDoLoopWithForallRefactoring extends FortranEditorRefactoring {
+
+ ASTProperLoopConstructNode selected_do_loop = null;
+ LinkedList<ASTProperLoopConstructNode> nested_selected_do_loop = new LinkedList<ASTProperLoopConstructNode>();
+
+ @Override
+ public String getName() {
+ return "Replace Do Loop By Forall";
+ }
+
+ @Override
+ protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ ensureProjectHasRefactoringEnabled(status);
+ LoopReplacer.replaceAllLoopsIn(this.astOfFileInEditor.getRoot());
+ IASTNode do_loop_node = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ if(!(do_loop_node instanceof ASTProperLoopConstructNode)){
+ fail("Please, select a Do Loop.");
+ }
+ // Find the selected loop.
+ selected_do_loop = findSelectedDoLoop();
+ // Checks if in the loops are made only assignments.
+ if(selected_do_loop != null){
+ IASTListNode<IExecutionPartConstruct> body_selected_loop = selected_do_loop.getBody();
+ for(IExecutionPartConstruct i : body_selected_loop){
+ if(!getBody(i)){
+ fail("Sorry, this refactoring can be applied only in Do Loops that contains just variable assignments.");
+ }
+ }
+ }
+ findNestedSelectedDoLoop();
+ }
+
+ private boolean getBody(IExecutionPartConstruct node){
+ if(node instanceof ASTProperLoopConstructNode){
+ IASTListNode<IExecutionPartConstruct> body = ((ASTProperLoopConstructNode)node).getBody();
+ for(IExecutionPartConstruct i : body){
+ if(i instanceof ASTProperLoopConstructNode){
+ return getBody(i);
+ }else{
+ if(!(i instanceof ASTAssignmentStmtNode)){
+ return false;
+ }
+ }
+ }
+ }else if(!(node instanceof ASTAssignmentStmtNode)){
+ return false;
+ }
+ return true;
+ }
+
+ private ASTProperLoopConstructNode findSelectedDoLoop() {
+ return getLoopNode(this.astOfFileInEditor, this.selectedRegionInEditor);
+ }
+
+ private void findNestedSelectedDoLoop(){
+ if(selected_do_loop != null){
+ IASTListNode<IExecutionPartConstruct> body_selected_loop = selected_do_loop.getBody();
+ for(IExecutionPartConstruct i : body_selected_loop){
+ addNestedSelectedDoLoop(i);
+ }
+ }
+ }
+
+ private void addNestedSelectedDoLoop(IExecutionPartConstruct node){
+ if(node instanceof ASTProperLoopConstructNode){
+ nested_selected_do_loop.add((ASTProperLoopConstructNode)node);
+ IASTListNode<IExecutionPartConstruct> body = ((ASTProperLoopConstructNode)node).getBody();
+ for(IExecutionPartConstruct i : body){
+ if(i instanceof ASTProperLoopConstructNode){
+ addNestedSelectedDoLoop(i);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ // There is no final conditions to check...
+ }
+
+ @Override
+ protected void doCreateChange(IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
+ for(int i=nested_selected_do_loop.size()-1; i>=0; i--){
+ ASTProperLoopConstructNode node = nested_selected_do_loop.get(i);
+ // Constructs a new FORALL node with the contents of the DO node and replaces in the AST.
+ String forall = constructForallNode(node);
+ node.replaceWith(parseLiteralStatementSequence(forall));
+ }
+ String forall = constructForallNode(selected_do_loop);
+ selected_do_loop.replaceWith(parseLiteralStatementSequence(forall));
+ addChangeFromModifiedAST(fileInEditor, progressMonitor);
+ vpg.releaseAST(fileInEditor);
+ }
+
+ // Constructs a new FORALL node.
+ private String constructForallNode(ASTProperLoopConstructNode node){
+ String variable = node.getLoopHeader().getLoopControl().getVariableName().getText();
+ String initial_value = node.getLoopHeader().getLoopControl().getLb().toString().trim();
+ String final_value = node.getLoopHeader().getLoopControl().getUb().toString().trim();
+ String tab_init = node.findFirstToken().getWhiteBefore();
+ String tab_end = node.getEndDoStmt().findFirstToken().getWhiteBefore();
+ String step = null;
+ IExpr step_expr = node.getLoopHeader().getLoopControl().getStep();
+ if(step_expr != null){
+ step = step_expr.toString();
+ }
+ String forall = tab_init + "FORALL (" + variable + "=" + initial_value + ":" + final_value; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if(step != null){
+ forall += ":" + step + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }else{
+ forall += ")"; //$NON-NLS-1$
+ }
+ String body = node.getBody().toString();
+ forall += "\n" + body + tab_end + "END FORALL"; //$NON-NLS-1$ //$NON-NLS-2$
+ return forall;
+ }
+}
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/TransformToDerivedDataTypeRefactoring.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/TransformToDerivedDataTypeRefactoring.java
new file mode 100644
index 00000000..09bae7bb
--- /dev/null
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/TransformToDerivedDataTypeRefactoring.java
@@ -0,0 +1,304 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.core.refactoring;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.photran.internal.core.analysis.binding.Definition;
+import org.eclipse.photran.internal.core.analysis.binding.ScopingNode;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode;
+import org.eclipse.photran.internal.core.parser.ASTEntityDeclNode;
+import org.eclipse.photran.internal.core.parser.ASTImplicitStmtNode;
+import org.eclipse.photran.internal.core.parser.ASTObjectNameNode;
+import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode;
+import org.eclipse.photran.internal.core.parser.IASTListNode;
+import org.eclipse.photran.internal.core.parser.IASTNode;
+import org.eclipse.photran.internal.core.parser.IBodyConstruct;
+import org.eclipse.photran.internal.core.vpg.PhotranTokenRef;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring;
+
+/**
+ * Refactoring that converts local variable declarations into a derived type.
+ *
+ * @author Gustavo Risetti
+ */
+@SuppressWarnings("nls") // TODO: Externalize strings
+public class TransformToDerivedDataTypeRefactoring extends FortranEditorRefactoring {
+
+ private static final String OPS = "ops"; //$NON-NLS-1$
+
+ private LinkedList<IBodyConstruct> statements_nodes = new LinkedList<IBodyConstruct>();
+ private LinkedList<PhotranTokenRef> references = new LinkedList<PhotranTokenRef>();
+ private String derivedTypeVariableName;
+ private String derivedTypeName;
+
+ @Override
+ public String getName() {
+ return "Transform To Derived Data Type";
+ }
+
+ public void setDerivedTypeName(String name) {
+ assert name != null;
+ derivedTypeName = name;
+ }
+
+ public void setDerivedTypeVariableName(String name) {
+ assert name != null;
+ derivedTypeVariableName = name;
+ }
+
+ // Search the beginning of variable declarations in each selected row, and checks
+ // if are used attributes that are not allowed in derived types.
+ private String findStatements(String s){
+ final String[] attributes_not_allowed = {"parameter", "intent", "target", "optional", "save", "external", "intrinsic"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+ final String[] types_allowed = {"integer", "real", "complex", "character", "logical"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ String statement_line = new String();
+ boolean has_type_in_line = false;
+ boolean init = false;
+ int j=0;
+ if(s.length() == 0){
+ return OPS;
+ }else{
+ for(int i = 0; i < s.length(); i++){
+ if(s.charAt(i) == ' ' || s.charAt(i) == '\t' && init == false){
+ j++;
+ }else{
+ init = true;
+ break;
+ }
+ }
+ if(s.charAt(j) == '!'){
+ return OPS;
+ }else{
+ statement_line = s.substring(j);
+ }
+ }
+ for(String type : types_allowed){
+ if(statement_line.toLowerCase().contains(type)){
+ has_type_in_line = true;
+ }
+ }
+ for(String attribute : attributes_not_allowed){
+ if(statement_line.toLowerCase().contains(attribute)){
+ has_type_in_line = false;
+ }
+ }
+ if(has_type_in_line){
+ return statement_line;
+ }else{
+ return OPS;
+ }
+ }
+
+ @Override
+ protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ final String SELECT_DECLARATION_WARNING = "Please select a variable declaration (or a list of variable declarations).";
+ final String USE_IN_DERIVED_TYPE_WARNING = "You can not use this refactoring within a Derived Data Type that already exists.";
+ ensureProjectHasRefactoringEnabled(status);
+ // Checks if variables were selected in a derived type that already exists.
+ IASTNode derived_type_node = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ ScopingNode derived_type_scope = ScopingNode.getEnclosingScope(derived_type_node);
+ if(derived_type_scope instanceof ASTDerivedTypeDefNode){
+ fail(USE_IN_DERIVED_TYPE_WARNING);
+ }
+ String selected_text = selectedRegionInEditor.getText();
+ if (selected_text.isEmpty()){
+ fail(SELECT_DECLARATION_WARNING);
+ }else{
+ String selected_lines[] = selected_text.split("\n"); //$NON-NLS-1$
+ for(String s : selected_lines){
+ s = findStatements(s);
+ if(!s.equalsIgnoreCase(OPS)){
+ statements_nodes.add(parseLiteralStatement(s));
+ }
+ }
+ LinkedList<IBodyConstruct> nodes_to_remove = new LinkedList<IBodyConstruct>();
+ for( IBodyConstruct node : statements_nodes){
+ if(!(node instanceof ASTTypeDeclarationStmtNode)){
+ nodes_to_remove.add(node);
+ }
+ }
+ // List of variables to be included in the new derived type.
+ statements_nodes.removeAll(nodes_to_remove);
+ }
+ if(statements_nodes.isEmpty()){
+ fail(SELECT_DECLARATION_WARNING);
+ }
+ }
+
+ @Override
+ protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure {
+ final String VALID_NAMES_WARNING = "Fill in the fields with valid values.";
+ final String SPACE_TD_WARNING = "The name of the Derived Data Type can not contain spaces and exclamation points.";
+ final String SPACE_VTD_WARNING = "The name of the new variable can not contain spaces and exclamation points.";
+ final String NUMERIC_DIGITS_WARNING = "The names created can not start with numeric digits.";
+ final Character[] numeric_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+ if(derivedTypeName.length() < 1 || derivedTypeVariableName.length() < 1){
+ fail(VALID_NAMES_WARNING);
+ }
+ for(int i = 0; i< derivedTypeName.length(); i++){
+ if(derivedTypeName.charAt(i) == ' ' || derivedTypeName.charAt(i) == '!' || derivedTypeName.charAt(i) == '\t'){
+ fail(SPACE_TD_WARNING);
+ }
+ }
+ for(int i = 0; i< derivedTypeVariableName.length(); i++){
+ if(derivedTypeVariableName.charAt(i) == ' ' || derivedTypeVariableName.charAt(i) == '!' || derivedTypeVariableName.charAt(i) == '\t'){
+ fail(SPACE_VTD_WARNING);
+ }
+ }
+ for(int i=0; i<numeric_digits.length; i++){
+ if(derivedTypeName.charAt(0) == numeric_digits[i] || derivedTypeVariableName.charAt(0) == numeric_digits[i]){
+ fail(NUMERIC_DIGITS_WARNING);
+ }
+ }
+ }
+
+ @SuppressWarnings("static-access")
+ @Override
+ protected void doCreateChange(IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
+ List<Character> blank_characters = new LinkedList<Character>();
+ IASTNode node = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
+ ScopingNode scope = astOfFileInEditor.getRoot().getEnclosingScope(node);
+ // Find where to add the declaration of the new derived type.
+ Token tokenToInsertDerivedDataType;
+ String tokenText;
+ tokenToInsertDerivedDataType = scope.getHeaderStmt().findLastToken();
+ IASTListNode< ? extends IASTNode> scopebody = scope.getBody();
+ for(IASTNode scopenode : scopebody){
+ if(scopenode instanceof ASTImplicitStmtNode){
+ ASTImplicitStmtNode implicitnode = (ASTImplicitStmtNode)scopenode;
+ tokenToInsertDerivedDataType = implicitnode.findLastToken();
+ break;
+ }
+ }
+ tokenText = tokenToInsertDerivedDataType.getText();
+ // Get indentation.
+ String tab = ""; //$NON-NLS-1$
+ String headerStmt = scope.getHeaderStmt().toString();
+ String[] headerStmtWithoutComments = headerStmt.split("\n");
+ headerStmt = headerStmtWithoutComments[headerStmtWithoutComments.length - 1];
+ tab = getBlankCharacters(blank_characters, tab, headerStmt);
+ tab+="\t"; //$NON-NLS-1$
+ // Construct the new node.
+ String new_derived_type = new String();
+ new_derived_type = tab + "TYPE " + derivedTypeName + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ for(IBodyConstruct s : statements_nodes){
+ new_derived_type += tab + "\t" + ((ASTTypeDeclarationStmtNode)s).toString(); //$NON-NLS-1$
+ }
+ new_derived_type += tab + "END TYPE " + derivedTypeName; //$NON-NLS-1$
+ // Declaration of a derived type variable.
+ new_derived_type += "\n\n" + tab + "TYPE("+derivedTypeName+") :: "+ derivedTypeVariableName + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ tokenToInsertDerivedDataType.setText(tokenText.trim() + "\n" + new_derived_type + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ // Search references of variables added to the new type and replace the references by the new type.
+ findReferences(scope);
+ if(statements_nodes.size() > 0){
+ addChangeFromModifiedAST(fileInEditor, progressMonitor);
+ }
+ vpg.releaseAST(fileInEditor);
+ }
+
+ void findReferences(ScopingNode scope){
+ List<Definition> used_definitions = new LinkedList<Definition>();
+ List<Definition> all_definitions = scope.getAllDefinitions();
+ LinkedList<String> node_names = new LinkedList<String>();
+ // Gets the names of the derived type variables.
+ for(IBodyConstruct t : statements_nodes){
+ IASTListNode<ASTEntityDeclNode> statements = ((ASTTypeDeclarationStmtNode)t).getEntityDeclList();
+ for(ASTEntityDeclNode d : statements){
+ node_names.add(d.getObjectName().toString().trim());
+ }
+ }
+ // Stores the definitions of variables actually used.
+ for(Definition def : all_definitions){
+ for(String n : node_names){
+ if(def.getDeclaredName().toString().trim().equals(n)){
+ used_definitions.add(def);
+ }
+ }
+ }
+ // Stores references to each definition actually used.
+ for(Definition d : used_definitions){
+ Set<PhotranTokenRef> references_to_definition = d.findAllReferences(false);
+ for(PhotranTokenRef t : references_to_definition){
+ references.add(t);
+ }
+ }
+ // Replaces references with the new type, with the access modifier %.
+ for(PhotranTokenRef t : references){
+ t.findToken().setText(derivedTypeVariableName+"%"+t.findToken().getText()); //$NON-NLS-1$
+ }
+ // Remove the declarations of variables that were included in the new derived type.
+ for(Definition def : used_definitions){
+ try {
+ removeVariableDeclFor(def);
+ } catch (PreconditionFailure e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ private void removeVariableDeclFor(Definition def) throws PreconditionFailure {
+ ASTTypeDeclarationStmtNode declarationNode = getTypeDeclarationStmtNode(def.getTokenRef().findToken().getParent());
+ IASTListNode<ASTEntityDeclNode> entityDeclList = declarationNode.getEntityDeclList();
+ if (entityDeclList.size() == 1) {
+ declarationNode.findFirstToken().setWhiteBefore(""); //$NON-NLS-1$
+ declarationNode.replaceWith(""); //$NON-NLS-1$
+ }else {
+ removeVariableDeclFromList(def, entityDeclList);
+ }
+ }
+
+ private void removeVariableDeclFromList(Definition def, IASTListNode<ASTEntityDeclNode> entityDeclList) throws PreconditionFailure {
+ for (ASTEntityDeclNode decl : entityDeclList) {
+ ASTObjectNameNode objectName = decl.getObjectName();
+ String declName = objectName.getObjectName().getText();
+ if (declName.equals(def.getDeclaredName())) {
+ if (!entityDeclList.remove(decl)) {
+ fail("The operation could not be completed.");
+ }
+ break;
+ }
+ }
+ entityDeclList.findFirstToken().setWhiteBefore(" "); //$NON-NLS-1$
+ }
+
+ private ASTTypeDeclarationStmtNode getTypeDeclarationStmtNode(IASTNode node) {
+ if (node == null){
+ return null;
+ }else if (node instanceof ASTTypeDeclarationStmtNode){
+ return (ASTTypeDeclarationStmtNode)node;
+ }else{
+ return getTypeDeclarationStmtNode(node.getParent());
+ }
+ }
+
+ private String getBlankCharacters(List<Character> blank_characters, String tab, String headerStmt) {
+ boolean start = false;
+ for(int i=0; i<headerStmt.length(); i++){
+ char c = headerStmt.charAt(i);
+ if((c != '\t') && (c != ' ')){
+ start = true;
+ }
+ if((c == '\t' || c == ' ') && !start){
+ blank_characters.add(headerStmt.charAt(i));
+ }
+ }
+ for(int i=0; i<blank_characters.size();i++){
+ tab+=blank_characters.get(i);
+ }
+ return tab;
+ }
+}
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/messages.properties b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/messages.properties
index 3de7224c..b494cb5d 100644
--- a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/messages.properties
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/messages.properties
@@ -183,7 +183,7 @@ RemoveRealAndDoublePrecisionLoopCountersRefactoring_PleaseSelectACountedDoLoop=P
RemoveRealAndDoublePrecisionLoopCountersRefactoring_PleaseSelectADoLoop=Please select a DO loop.
RemoveUnreferencedLabelsRefactoring_Name=Remove Unreferenced Labels
RemoveUnreferencedLabelsRefactoring_ThereMustBeAtLeastOneLabeledStatement=To perform this refactoring, there MUST be at least one labeled statement.
-RemoveUnusedVariablesRefactoring_CouldNotCompleteOperation=Sorry, could not complete the operation.
+RemoveUnusedVariablesRefactoring_CouldNotCompleteOperation=The operation could not be completed.
RemoveUnusedVariablesRefactoring_DoesNotRemovedUnusedVarsWithDefsOnAnotherLine=This refactoring does not remove unused variables when their dimentions are specified on another line. I.e. real a /n/n dimention a(10) will not be removed.
RemoveUnusedVariablesRefactoring_Name=Remove Unused Local Variables
RemoveUnusedVariablesRefactoring_RefactorAgainToRemoveAllUnusedVars=After clicking 'Continue', do the same refactoring again to make sure that all unused variables are removed from file {0}!
diff --git a/org.eclipse.photran.ui.vpg/plugin.xml b/org.eclipse.photran.ui.vpg/plugin.xml
index c34a91f2..5724ffbd 100644
--- a/org.eclipse.photran.ui.vpg/plugin.xml
+++ b/org.eclipse.photran.ui.vpg/plugin.xml
@@ -31,7 +31,16 @@
inputPage="org.eclipse.photran.internal.ui.refactoring.PermuteSubroutineArgsInputPage"
/>
<editorRefactoring
- class = "org.eclipse.photran.internal.core.refactoring.SafeDeleteInternalSubprogramRefactoring"
+ class="org.eclipse.photran.internal.core.refactoring.SafeDeleteInternalSubprogramRefactoring"
+ />
+ <editorRefactoring
+ command="org.eclipse.photran.ui.ExtractSubprogramToModuleRefactoringCommand"
+ />
+ <editorRefactoring
+ command="org.eclipse.photran.ui.MoveSubprogramToModuleRefactoringCommand"
+ />
+ <resourceRefactoring
+ class="org.eclipse.photran.internal.core.refactoring.IntroduceCallTreeRefactoring"
/>
</submenu>
</group>
@@ -69,6 +78,16 @@
</submenu>
</group>
<group>
+ <submenu name="Derived Type"><!-- Refactorings for derived types -->
+ <editorRefactoring
+ command="org.eclipse.photran.ui.AddVariableToDerivedDataTypeRefactoringCommand"
+ />
+ <editorRefactoring
+ command="org.eclipse.photran.ui.TransformToDerivedDataTypeRefactoringCommand"
+ />
+ </submenu>
+ </group>
+ <group>
<submenu name="Do Loop"><!-- Loop transformations (for performance improvement) -->
<editorRefactoring
class="org.eclipse.photran.internal.core.refactoring.InterchangeLoopsRefactoring"
@@ -85,6 +104,9 @@
<editorRefactoring
class="org.eclipse.photran.internal.core.refactoring.UnrollLoopRefactoring"
/>
+ <editorRefactoring
+ command="org.eclipse.photran.ui.ReplaceDoLoopWithForallRefactoringCommand"
+ />
</submenu>
</group>
<group>
@@ -132,6 +154,9 @@
command="org.eclipse.photran.ui.IfConstructStatementConversionRefactoringCommand"
/>
<resourceRefactoring
+ class="org.eclipse.photran.internal.core.refactoring.NestedIfThenElseToSelectCaseRefactoring"
+ />
+ <resourceRefactoring
class="org.eclipse.photran.internal.core.refactoring.DataToParameterRefactoring"
/>
<resourceRefactoring
@@ -198,6 +223,31 @@
categoryId="org.eclipse.photran.ui.RefactoringCategory"
id="org.eclipse.photran.ui.AddSubroutineParameterRefactoringCommand">
</command>
+ <command
+ name="Add Variable to Derived Data Type..."
+ categoryId="org.eclipse.photran.ui.RefactoringCategory"
+ id="org.eclipse.photran.ui.AddVariableToDerivedDataTypeRefactoringCommand">
+ </command>
+ <command
+ name="Extract Subprogram to Module..."
+ categoryId="org.eclipse.photran.ui.RefactoringCategory"
+ id="org.eclipse.photran.ui.ExtractSubprogramToModuleRefactoringCommand">
+ </command>
+ <command
+ name="Move Subprogram to Module..."
+ categoryId="org.eclipse.photran.ui.RefactoringCategory"
+ id="org.eclipse.photran.ui.MoveSubprogramToModuleRefactoringCommand">
+ </command>
+ <command
+ name="Replace Do Loop with Forall..."
+ categoryId="org.eclipse.photran.ui.RefactoringCategory"
+ id="org.eclipse.photran.ui.ReplaceDoLoopWithForallRefactoringCommand">
+ </command>
+ <command
+ name="Transform to Derived Data Type..."
+ categoryId="org.eclipse.photran.ui.RefactoringCategory"
+ id="org.eclipse.photran.ui.TransformToDerivedDataTypeRefactoringCommand">
+ </command>
</extension>
<!-- 2. Optionally associate the command with an accelerator key -->
@@ -273,6 +323,31 @@
definitionId="org.eclipse.photran.ui.AddSubroutineParameterRefactoringCommand"
class="org.eclipse.photran.internal.ui.refactoring.AddSubroutineParameterAction"
id="org.eclipse.photran.ui.AddSubroutineParameterRefactoringAction"/>
+ <action
+ label="Add Variable to Derived Data Type"
+ definitionId="org.eclipse.photran.ui.AddVariableToDerivedDataTypeRefactoringCommand"
+ class="org.eclipse.photran.internal.ui.refactoring.AddVariableToDerivedDataTypeAction"
+ id="org.eclipse.photran.ui.AddVariableToDerivedDataTypeRefactoringAction"/>
+ <action
+ label="Extract Subprogram to Module"
+ definitionId="org.eclipse.photran.ui.ExtractSubprogramToModuleRefactoringCommand"
+ class="org.eclipse.photran.internal.ui.refactoring.ExtractSubprogramToModuleAction"
+ id="org.eclipse.photran.ui.ExtractSubprogramToModuleRefactoringAction"/>
+ <action
+ label="Move Subprogram to Module"
+ definitionId="org.eclipse.photran.ui.MoveSubprogramToModuleRefactoringCommand"
+ class="org.eclipse.photran.internal.ui.refactoring.MoveSubprogramToModuleAction"
+ id="org.eclipse.photran.ui.MoveSubprogramToModuleRefactoringAction"/>
+ <action
+ label="Replace Do Loop with Forall"
+ definitionId="org.eclipse.photran.ui.ReplaceDoLoopWithForallRefactoringCommand"
+ class="org.eclipse.photran.internal.ui.refactoring.ReplaceDoLoopWithForallAction"
+ id="org.eclipse.photran.ui.ReplaceDoLoopWithForallRefactoringAction"/>
+ <action
+ label="Transform to Derived Data Type"
+ definitionId="org.eclipse.photran.ui.TransformToDerivedDataTypeRefactoringCommand"
+ class="org.eclipse.photran.internal.ui.refactoring.TransformToDerivedDataTypeAction"
+ id="org.eclipse.photran.ui.TransformToDerivedDataTypeRefactoringAction"/>
</actionSet>
</extension>
diff --git a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/AddVariableToDerivedDataTypeAction.java b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/AddVariableToDerivedDataTypeAction.java
new file mode 100644
index 00000000..e83893e0
--- /dev/null
+++ b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/AddVariableToDerivedDataTypeAction.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.ui.refactoring;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.photran.core.IFortranAST;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.refactoring.AddVariableToDerivedDataTypeRefactoring;
+import org.eclipse.photran.internal.core.vpg.PhotranVPG;
+import org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * User interface/action handler for {@link AddVariableToDerivedDataTypeRefactoring}.
+ *
+ * @author Gustavo Risetti
+ */
+public class AddVariableToDerivedDataTypeAction
+ extends AbstractFortranRefactoringActionDelegate
+ implements IWorkbenchWindowActionDelegate, IEditorActionDelegate
+{
+ public AddVariableToDerivedDataTypeAction()
+ {
+ super(AddVariableToDerivedDataTypeRefactoring.class, FortranAddVariableToDerivedDataTypeRefactoringWizard.class);
+ }
+
+ @Override
+ protected VPGRefactoring<IFortranAST, Token, PhotranVPG> getRefactoring(List<IFile> files)
+ {
+ AddVariableToDerivedDataTypeRefactoring r = new AddVariableToDerivedDataTypeRefactoring();
+ r.initialize(
+ getFortranEditor().getIFile(),
+ getFortranEditor().getSelection());
+ return r;
+ }
+
+ public static class FortranAddVariableToDerivedDataTypeRefactoringWizard extends AbstractFortranRefactoringWizard
+ {
+ protected AddVariableToDerivedDataTypeRefactoring addVariableToDerivedDataTypeRefactoring;
+
+ public FortranAddVariableToDerivedDataTypeRefactoringWizard(AddVariableToDerivedDataTypeRefactoring r)
+ {
+ super(r);
+ this.addVariableToDerivedDataTypeRefactoring = r;
+ }
+
+ @Override
+ protected void doAddUserInputPages()
+ {
+ addPage(new UserInputWizardPage(addVariableToDerivedDataTypeRefactoring.getName())
+ {
+ protected Text derivedDataTypeName;
+ protected Text variableName;
+
+ public void createControl(Composite parent)
+ {
+ Composite top = new Composite(parent, SWT.NONE);
+ initializeDialogUnits(top);
+ setControl(top);
+
+ top.setLayout(new GridLayout(2, false));
+
+ Composite group = top;
+ Label lbl = new Label(group, SWT.NONE);
+ lbl.setText(Messages.AddVariableToDerivedDataTypeAction_label1Text);
+
+ derivedDataTypeName = new Text(group, SWT.BORDER);
+ derivedDataTypeName.setText(""); //$NON-NLS-1$
+ derivedDataTypeName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ derivedDataTypeName.selectAll();
+ derivedDataTypeName.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ addVariableToDerivedDataTypeRefactoring.setDerivedTypeName(derivedDataTypeName.getText());
+ }
+ });
+
+ Label lbl2 = new Label(group, SWT.NONE);
+ lbl2.setText(Messages.AddVariableToDerivedDataTypeAction_label2Text);
+
+ variableName = new Text(group, SWT.BORDER);
+ variableName.setText(""); //$NON-NLS-1$
+ variableName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ variableName.selectAll();
+ variableName.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ addVariableToDerivedDataTypeRefactoring.setDerivedTypeVariableName(variableName.getText());
+ }
+ });
+
+ // Call once for sure, just in case the user doesn't modify the text
+ addVariableToDerivedDataTypeRefactoring.setDerivedTypeName(derivedDataTypeName.getText());
+ addVariableToDerivedDataTypeRefactoring.setDerivedTypeVariableName(derivedDataTypeName.getText());
+
+ derivedDataTypeName.setFocus();
+ }
+ });
+ }
+ }
+}
diff --git a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ExtractSubprogramToModuleAction.java b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ExtractSubprogramToModuleAction.java
new file mode 100644
index 00000000..852a87d9
--- /dev/null
+++ b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ExtractSubprogramToModuleAction.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.ui.refactoring;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.photran.core.IFortranAST;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.refactoring.ExtractSubprogramToModuleRefactoring;
+import org.eclipse.photran.internal.core.vpg.PhotranVPG;
+import org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * User interface/action handler for {@link ExtractSubprogramToModuleRefactoring}.
+ *
+ * @author Gustavo Risetti
+ */
+public class ExtractSubprogramToModuleAction
+ extends AbstractFortranRefactoringActionDelegate
+ implements IWorkbenchWindowActionDelegate, IEditorActionDelegate
+{
+ public ExtractSubprogramToModuleAction()
+ {
+ super(ExtractSubprogramToModuleRefactoring.class, FortranInsertFunctionOrSubroutineInModuleRefactoringWizard.class);
+ }
+
+ @Override
+ protected VPGRefactoring<IFortranAST, Token, PhotranVPG> getRefactoring(List<IFile> files)
+ {
+ ExtractSubprogramToModuleRefactoring r = new ExtractSubprogramToModuleRefactoring();
+ r.initialize(
+ getFortranEditor().getIFile(),
+ getFortranEditor().getSelection());
+ return r;
+ }
+
+ public static class FortranInsertFunctionOrSubroutineInModuleRefactoringWizard extends AbstractFortranRefactoringWizard
+ {
+ protected ExtractSubprogramToModuleRefactoring extractSubroutineOrFunctionToModuleRefactoring;
+
+ public FortranInsertFunctionOrSubroutineInModuleRefactoringWizard(ExtractSubprogramToModuleRefactoring r)
+ {
+ super(r);
+ this.extractSubroutineOrFunctionToModuleRefactoring = r;
+ }
+
+ @Override
+ protected void doAddUserInputPages()
+ {
+ addPage(new UserInputWizardPage(extractSubroutineOrFunctionToModuleRefactoring.getName())
+ {
+ protected Text newNameField;
+ public void createControl(Composite parent)
+ {
+ Composite top = new Composite(parent, SWT.NONE);
+ initializeDialogUnits(top);
+ setControl(top);
+
+ top.setLayout(new GridLayout(1, false));
+
+ Composite group = top;
+ Label lbl = new Label(group, SWT.NONE);
+ lbl.setText(Messages.ExtractSubprogramToModuleAction_labelText);
+
+ newNameField = new Text(group, SWT.BORDER);
+ newNameField.setText(""); //$NON-NLS-1$
+ newNameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ newNameField.selectAll();
+ newNameField.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ extractSubroutineOrFunctionToModuleRefactoring.setModuleName(newNameField.getText());
+ }
+ });
+
+ extractSubroutineOrFunctionToModuleRefactoring.setModuleName(newNameField.getText());
+ newNameField.setFocus();
+ }
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/Messages.java b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/Messages.java
index e85cb8ad..861d4134 100644
--- a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/Messages.java
+++ b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/Messages.java
@@ -78,6 +78,8 @@ public class Messages extends NLS
public static String ExtractProcedureAction_SubroutineNameLabel;
+ public static String ExtractSubprogramToModuleAction_labelText;
+
public static String KeywordCaseInputPage_ChangeKeywordsToLabel;
public static String KeywordCaseInputPage_ClickOKMessage;
@@ -94,6 +96,8 @@ public class Messages extends NLS
public static String MoveFromModuleInputPage_selectDataMessage;
+ public static String MoveSubprogramToModuleAction_labelText;
+
public static String RenameAction_MatchExternalSubprograms;
public static String RenameAction_RenameAtoB;
@@ -112,11 +116,21 @@ public class Messages extends NLS
public static String RemoveRealAndDoublePrecisionLoopCountersInputPage_ClickPreviewMessage;
+ public static String ReplaceDoLoopWithForallAction_messageText;
+
public static String AddSubroutineParameterAction_DefaultLabel;
public static String AddSubroutineParameterAction_DeclarationLabel;
public static String AddSubroutineParameterAction_LocationLabel;
+
+ public static String AddVariableToDerivedDataTypeAction_label1Text;
+
+ public static String AddVariableToDerivedDataTypeAction_label2Text;
+
+ public static String TransformToDerivedDataTypeAction_label1Text;
+
+ public static String TransformToDerivedDataTypeAction_label2Text;
static
{
diff --git a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/MoveSubprogramToModuleAction.java b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/MoveSubprogramToModuleAction.java
new file mode 100644
index 00000000..25f9bbdf
--- /dev/null
+++ b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/MoveSubprogramToModuleAction.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.ui.refactoring;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.photran.core.IFortranAST;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.refactoring.AddVariableToDerivedDataTypeRefactoring;
+import org.eclipse.photran.internal.core.refactoring.MoveSubprogramToModuleRefactoring;
+import org.eclipse.photran.internal.core.vpg.PhotranVPG;
+import org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * User interface/action handler for {@link AddVariableToDerivedDataTypeRefactoring}.
+ *
+ * @author Gustavo Risetti
+ */
+public class MoveSubprogramToModuleAction
+ extends AbstractFortranRefactoringActionDelegate
+ implements IWorkbenchWindowActionDelegate, IEditorActionDelegate
+{
+ public MoveSubprogramToModuleAction()
+ {
+ super(MoveSubprogramToModuleRefactoring.class, FortranMoveSubroutineOrFunctionToModuleRefactoringWizard.class);
+ }
+
+ @Override
+ protected VPGRefactoring<IFortranAST, Token, PhotranVPG> getRefactoring(List<IFile> files)
+ {
+ MoveSubprogramToModuleRefactoring r = new MoveSubprogramToModuleRefactoring();
+ r.initialize(
+ getFortranEditor().getIFile(),
+ getFortranEditor().getSelection());
+ return r;
+ }
+
+ public static class FortranMoveSubroutineOrFunctionToModuleRefactoringWizard extends AbstractFortranRefactoringWizard
+ {
+ protected MoveSubprogramToModuleRefactoring moveSubroutineOrFunctionToModuleRefactoring;
+
+ public FortranMoveSubroutineOrFunctionToModuleRefactoringWizard(MoveSubprogramToModuleRefactoring r)
+ {
+ super(r);
+ this.moveSubroutineOrFunctionToModuleRefactoring = r;
+ }
+
+ @Override
+ protected void doAddUserInputPages()
+ {
+ addPage(new UserInputWizardPage(moveSubroutineOrFunctionToModuleRefactoring.getName())
+ {
+ protected Text newNameField;
+ public void createControl(Composite parent)
+ {
+ Composite top = new Composite(parent, SWT.NONE);
+ initializeDialogUnits(top);
+ setControl(top);
+
+ top.setLayout(new GridLayout(1, false));
+
+ Composite group = top;
+ Label lbl = new Label(group, SWT.NONE);
+ lbl.setText(Messages.MoveSubprogramToModuleAction_labelText);
+
+ newNameField = new Text(group, SWT.BORDER);
+ newNameField.setText(""); //$NON-NLS-1$
+ newNameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ newNameField.selectAll();
+ newNameField.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ moveSubroutineOrFunctionToModuleRefactoring.setModuleName(newNameField.getText());
+ }
+ });
+
+ moveSubroutineOrFunctionToModuleRefactoring.setModuleName(newNameField.getText());
+ newNameField.setFocus();
+ }
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ReplaceDoLoopWithForallAction.java b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ReplaceDoLoopWithForallAction.java
new file mode 100644
index 00000000..0008f291
--- /dev/null
+++ b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/ReplaceDoLoopWithForallAction.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.ui.refactoring;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.photran.core.IFortranAST;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.refactoring.ReplaceDoLoopWithForallRefactoring;
+import org.eclipse.photran.internal.core.vpg.PhotranVPG;
+import org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * User interface/action handler for {@link ReplaceDoLoopWithForallRefactoring}.
+ *
+ * @author Gustavo Risetti
+ */
+public class ReplaceDoLoopWithForallAction
+ extends AbstractFortranRefactoringActionDelegate
+ implements IWorkbenchWindowActionDelegate, IEditorActionDelegate
+{
+ public ReplaceDoLoopWithForallAction()
+ {
+ super(ReplaceDoLoopWithForallRefactoring.class, FortranReplaceDoLoopByForallRefactoringWizard.class);
+ }
+
+ @Override
+ protected VPGRefactoring<IFortranAST, Token, PhotranVPG> getRefactoring(List<IFile> files)
+ {
+ ReplaceDoLoopWithForallRefactoring r = new ReplaceDoLoopWithForallRefactoring();
+ r.initialize(
+ getFortranEditor().getIFile(),
+ getFortranEditor().getSelection());
+ return r;
+ }
+
+ public static class FortranReplaceDoLoopByForallRefactoringWizard extends AbstractFortranRefactoringWizard
+ {
+ protected ReplaceDoLoopWithForallRefactoring replaceDoLoopByForallRefactoring;
+
+ public FortranReplaceDoLoopByForallRefactoringWizard(ReplaceDoLoopWithForallRefactoring r)
+ {
+ super(r);
+ this.replaceDoLoopByForallRefactoring = r;
+ }
+
+ @Override
+ protected void doAddUserInputPages()
+ {
+ addPage(new UserInputWizardPage(replaceDoLoopByForallRefactoring.getName())
+ {
+ public void createControl(Composite parent)
+ {
+ Composite top = new Composite(parent, SWT.NONE);
+ initializeDialogUnits(top);
+ setControl(top);
+
+ top.setLayout(new GridLayout(1, false));
+
+ Composite group = top;
+ Label lbl = new Label(group, SWT.NONE);
+ lbl.setText(Messages.ReplaceDoLoopWithForallAction_messageText);
+ }
+ });
+ }
+ }
+}
diff --git a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/TransformToDerivedDataTypeAction.java b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/TransformToDerivedDataTypeAction.java
new file mode 100644
index 00000000..489948dd
--- /dev/null
+++ b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/TransformToDerivedDataTypeAction.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2011 UFSM - Universidade Federal de Santa Maria (www.ufsm.br).
+ * 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.photran.internal.ui.refactoring;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.photran.core.IFortranAST;
+import org.eclipse.photran.internal.core.lexer.Token;
+import org.eclipse.photran.internal.core.refactoring.TransformToDerivedDataTypeRefactoring;
+import org.eclipse.photran.internal.core.vpg.PhotranVPG;
+import org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * User interface/action handler for {@link TransformToDerivedDataTypeRefactoring}.
+ *
+ * @author Gustavo Risetti
+ */
+public class TransformToDerivedDataTypeAction
+ extends AbstractFortranRefactoringActionDelegate
+ implements IWorkbenchWindowActionDelegate, IEditorActionDelegate
+{
+ public TransformToDerivedDataTypeAction()
+ {
+ super(TransformToDerivedDataTypeRefactoring.class, FortranTransformToDerivedDataTypeRefactoringWizard.class);
+ }
+
+ @Override
+ protected VPGRefactoring<IFortranAST, Token, PhotranVPG> getRefactoring(List<IFile> files)
+ {
+ TransformToDerivedDataTypeRefactoring r = new TransformToDerivedDataTypeRefactoring();
+ r.initialize(
+ getFortranEditor().getIFile(),
+ getFortranEditor().getSelection());
+ return r;
+ }
+
+ public static class FortranTransformToDerivedDataTypeRefactoringWizard extends AbstractFortranRefactoringWizard
+ {
+ protected TransformToDerivedDataTypeRefactoring transformToDerivedDataTypeRefactoring;
+
+ public FortranTransformToDerivedDataTypeRefactoringWizard(TransformToDerivedDataTypeRefactoring r)
+ {
+ super(r);
+ this.transformToDerivedDataTypeRefactoring = r;
+ }
+
+ @Override
+ protected void doAddUserInputPages()
+ {
+ addPage(new UserInputWizardPage(transformToDerivedDataTypeRefactoring.getName())
+ {
+ protected Text newNameField;
+ protected Text newVariableName;
+
+ public void createControl(Composite parent)
+ {
+ Composite top = new Composite(parent, SWT.NONE);
+ initializeDialogUnits(top);
+ setControl(top);
+
+ top.setLayout(new GridLayout(2, false));
+
+ Composite group = top;
+ Label lbl = new Label(group, SWT.NONE);
+ lbl.setText(Messages.TransformToDerivedDataTypeAction_label1Text);
+
+ newNameField = new Text(group, SWT.BORDER);
+ newNameField.setText(""); //$NON-NLS-1$
+ newNameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ newNameField.selectAll();
+ newNameField.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ transformToDerivedDataTypeRefactoring.setDerivedTypeName(newNameField.getText());
+ }
+ });
+
+ Label lbl2 = new Label(group, SWT.NONE);
+ lbl2.setText(Messages.TransformToDerivedDataTypeAction_label2Text);
+
+ newVariableName = new Text(group, SWT.BORDER);
+ newVariableName.setText(""); //$NON-NLS-1$
+ newVariableName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ newVariableName.selectAll();
+ newVariableName.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ transformToDerivedDataTypeRefactoring.setDerivedTypeVariableName(newVariableName.getText());
+ }
+ });
+
+ // Call once for sure, just in case the user doesn't modify the text
+ transformToDerivedDataTypeRefactoring.setDerivedTypeName(newNameField.getText());
+ transformToDerivedDataTypeRefactoring.setDerivedTypeVariableName(newNameField.getText());
+
+ newNameField.setFocus();
+ }
+ });
+ }
+ }
+}
+
diff --git a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/messages.properties b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/messages.properties
index d8b1cc00..926e52a9 100644
--- a/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/messages.properties
+++ b/org.eclipse.photran.ui.vpg/src/org/eclipse/photran/internal/ui/refactoring/messages.properties
@@ -21,6 +21,7 @@ CommonVarNamesInputPage_NewNameLabel=New Name
CommonVarNamesInputPage_OriginalNameLabel=Original Name
ExtractLocalVariableAction_DeclarationLabel=Declaration:
ExtractProcedureAction_SubroutineNameLabel=Extract selected code to a subroutine named
+ExtractSubprogramToModuleAction_labelText=Extract Subroutine or Function to Module:
KeywordCaseInputPage_ChangeKeywordsToLabel=Change keywords to:
KeywordCaseInputPage_ClickOKMessage=Click OK to change the case of all keywords in the selected files. To see what changes will be made, click Preview.
KeywordCaseInputPage_LowerCaseLabel=Lower Case
@@ -29,6 +30,7 @@ MoveFromModuleInputPage_leftPanelMessage=Members to Move
MoveFromModuleInputPage_Name=Move From Module Refactoring
MoveFromModuleInputPage_rightPanelMessage=Destination Module
MoveFromModuleInputPage_selectDataMessage=Please select member data to move from module
+MoveSubprogramToModuleAction_labelText=Move Subroutine or Function to Module:
RenameAction_MatchExternalSubprograms=Match external subprograms with interfaces and external declarations
RenameAction_RenameAtoB=Rename {0} to
RemoveAssignGotoInputPage_Prompt=Add Default Case?
@@ -41,7 +43,12 @@ RemoveRealAndDoublePrecisionLoopCountersInputPage_ReplaceWithDoLoop=DO Loop
RemoveRealAndDoublePrecisionLoopCountersInputPage_ReplaceWithDoWhileLoop=DO WHILE Loop
RemoveRealAndDoublePrecisionLoopCountersInputPage_ClickOKMessage=Click OK to replace the real/double precision loop counter.
RemoveRealAndDoublePrecisionLoopCountersInputPage_ClickPreviewMessage=To see what the changes will be made, click Preview.
+ReplaceDoLoopWithForallAction_messageText=Click OK to replace the selected Do Loop by Forall. To see what changes will be made, click Preview.
AddSubroutineParameterAction_DeclarationLabel=Declaration:
AddSubroutineParameterAction_LocationLabel=Position:
AddSubroutineParameterAction_DefaultLabel=Default Value:
-IfConstructStatementConversionAction_AddEmptyElseBlock=Add Empty ELSE Block \ No newline at end of file
+AddVariableToDerivedDataTypeAction_label1Text=Derived Data Type to introduce the selected variable:
+AddVariableToDerivedDataTypeAction_label2Text=Derived Data Type instance to be used:
+IfConstructStatementConversionAction_AddEmptyElseBlock=Add Empty ELSE Block
+TransformToDerivedDataTypeAction_label1Text=Name the new Derived Data Type with the name:
+TransformToDerivedDataTypeAction_label2Text=Name the new variable with the name:

Back to the top