blob: 83cc64aff84ac2d9225cab003c90ebd6e9cb471a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 University of Illinois at Urbana-Champaign and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.photran.internal.core.refactoring;
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.ASTAccessStmtNode;
import org.eclipse.photran.internal.core.parser.ASTSubroutineNameNode;
import org.eclipse.photran.internal.core.parser.ASTSubroutineStmtNode;
import org.eclipse.photran.internal.core.parser.ASTSubroutineSubprogramNode;
import org.eclipse.photran.internal.core.parser.IASTListNode;
import org.eclipse.photran.internal.core.parser.IASTNode;
import org.eclipse.photran.internal.core.parser.IAccessId;
import org.eclipse.photran.internal.core.parser.IInternalSubprogram;
import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring;
import org.eclipse.photran.internal.core.vpg.PhotranTokenRef;
/**
* Refactoring to delete un-referenced internal subprograms.If the subprogram has only internal
* references then delete the subprogram in all cases.If the particular subprogram happens to be the
* only internal subprogram then remove the contains statement and any access statement.
*
* @author Abhishek Sharma
*/
public class SafeDeleteInternalSubprogramRefactoring extends FortranEditorRefactoring
{
private ASTSubroutineSubprogramNode subProgramNode;
@Override
protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm)
throws PreconditionFailure
{
ensureProjectHasRefactoringEnabled(status);
IASTNode selectedNode = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
if (selectedNode == null) fail(Messages.SafeDeleteInternalSubprogramRefactoring_NoSubroutineSelected);
if (selectedNode instanceof ASTSubroutineSubprogramNode)
subProgramNode = ((ASTSubroutineSubprogramNode)selectedNode);
else if (selectedNode instanceof ASTSubroutineStmtNode
|| selectedNode instanceof ASTSubroutineNameNode)
{
ASTSubroutineSubprogramNode NearestAncestor = selectedNode
.findNearestAncestor(ASTSubroutineSubprogramNode.class);
subProgramNode = NearestAncestor;
}
if (subProgramNode == null) fail(Messages.SafeDeleteInternalSubprogramRefactoring_NoSubroutineSelected);
// list of definitions.Ideally there should be only 1 element in the list
List<Definition> definitionsList = subProgramNode.getSubroutineStmt().getSubroutineName()
.getSubroutineName().resolveBinding();
if (definitionsList.size() == 0)
throw new PreconditionFailure(Messages.SafeDeleteInternalSubprogramRefactoring_NoDefinition);
else if (definitionsList.size() > 1)
throw new PreconditionFailure(Messages.SafeDeleteInternalSubprogramRefactoring_MultipleDefinitions);
else if (definitionsList.get(0).isInternalSubprogramDefinition() == false)
throw new PreconditionFailure(Messages.SafeDeleteInternalSubprogramRefactoring_NotAnInternalSubprogram);
for (PhotranTokenRef tokenRef : definitionsList.get(0).findAllReferences(true))
{
// token is neither in the access statement nor does it occur in itself(recursive)
if (tokenRef.findToken().findNearestAncestor(ASTAccessStmtNode.class) == null
&& tokenRef.findToken().findNearestAncestor(ASTSubroutineSubprogramNode.class) != subProgramNode)
fail(Messages.SafeDeleteInternalSubprogramRefactoring_SubroutineMustHaveOnlyInternalReferences);
}
}
@Override
protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm)
throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
{
}
@Override
protected void doCreateChange(IProgressMonitor pm) throws CoreException,
OperationCanceledException
{
removeReferenceInAccessStatement();
removeSubProgram();
this.addChangeFromModifiedAST(this.fileInEditor, pm);
vpg.releaseAllASTs();
}
private void removeSubProgram()
{
ScopingNode enclosingScope = subProgramNode.findNearestAncestor(ScopingNode.class);
if (enclosingScope != null)
{
IASTListNode<IInternalSubprogram> internalSubprogramList = enclosingScope.getInternalSubprograms();
if (internalSubprogramList.size() == 1)
enclosingScope.getContainsStmt().removeFromTree();
subProgramNode.removeFromTree();
}
}
private void removeReferenceInAccessStatement()
{
List<Definition> definitionsList = subProgramNode.getSubroutineStmt().getSubroutineName()
.getSubroutineName().resolveBinding();
for (PhotranTokenRef tokenRef : definitionsList.get(0).findAllReferences(true))
{
if (tokenRef.findToken().findNearestAncestor(ASTAccessStmtNode.class) != null)
{
IASTListNode<IAccessId> accessIdList = tokenRef.findToken()
.findNearestAncestor(ASTAccessStmtNode.class).getAccessIdList();
if (accessIdList.size() == 1)
tokenRef.findToken().findNearestAncestor(ASTAccessStmtNode.class)
.removeFromTree();
else
{
Token token = tokenRef.findToken();
IAccessId accessID = token.findNearestAncestor(IAccessId.class);
accessIdList.remove(accessID);
}
}
}
}
@Override
public String getName()
{
return Messages.SafeDeleteInternalSubprogramRefactoring_Name;
}
}