/* * Copyright (C) 2006, 2007 Dennis Hunziker, Ueli Kistler * Copyright (C) 2007 Reto Schuettel, Robin Stocker */ package org.python.pydev.refactoring.coderefactoring.inlinelocal; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.ITextSelection; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.Assign; import org.python.pydev.parser.jython.ast.Name; import org.python.pydev.parser.jython.ast.exprType; import org.python.pydev.parser.jython.ast.expr_contextType; import org.python.pydev.refactoring.ast.adapters.AbstractScopeNode; import org.python.pydev.refactoring.ast.visitors.LocalVariablesVisitor; import org.python.pydev.refactoring.core.base.AbstractPythonRefactoring; import org.python.pydev.refactoring.core.base.RefactoringInfo; import org.python.pydev.refactoring.core.change.IChangeProcessor; import org.python.pydev.refactoring.messages.Messages; public class InlineLocalRefactoring extends AbstractPythonRefactoring { private InlineLocalRequestProcessor requestProcessor; private IChangeProcessor changeProcessor; public InlineLocalRefactoring(RefactoringInfo info) { super(info); initWizard(); } private void initWizard() { this.requestProcessor = new InlineLocalRequestProcessor(info); } @Override protected List<IChangeProcessor> getChangeProcessors() { List<IChangeProcessor> processors = new ArrayList<IChangeProcessor>(); this.changeProcessor = new InlineLocalChangeProcessor(getName(), this.info, this.requestProcessor); processors.add(changeProcessor); return processors; } @Override public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { AbstractScopeNode<?> scope = info.getScopeAdapter(); ITextSelection selection = info.getUserSelection(); SimpleNode node = scope.getASTNode(); LocalVariablesVisitor visitor = new LocalVariablesVisitor(); try { node.accept(visitor); } catch (Exception e) { throw new RuntimeException(e); } List<Name> variables = visitor.getVariables(); Name selectedVariable = findSelectedVariable(selection, variables); if (selectedVariable == null) { status.addFatalError(Messages.validationNoNameSelected); return status; } List<Name> relatedVariables = findAllRelatedVariables(variables, selectedVariable); Assign assignment = findAssignment(relatedVariables); if (assignment == null) { String id = selectedVariable.id; status.addFatalError(Messages.format(Messages.inlinelocalNoAssignment, id)); return status; } if (!isValid(relatedVariables)) { return status; } requestProcessor.setAssign(assignment); requestProcessor.setVariables(relatedVariables); return status; } private boolean isValid(List<Name> variables) { int assignCounter = 0; for (Name variable : variables) { if (variable.parent instanceof Assign) { Assign assign = (Assign) variable.parent; /* The given name has to be one of the targets of this assignment */ for (exprType x : assign.targets) { if (x == variable) { assignCounter++; break; } } } if (variable.ctx == expr_contextType.Param || variable.ctx == expr_contextType.KwOnlyParam) { status.addFatalError(Messages.format(Messages.inlineLocalParameter, variable.getId())); return false; } } if (assignCounter > 1) { status.addFatalError(Messages.format(Messages.inlineLocalMultipleAssignments, variables.get(0).getId())); return false; } return true; } private Assign findAssignment(List<Name> relatedVariables) { /* Search for the assignment */ for (Name variable : relatedVariables) { SimpleNode parent = variable.parent; if (parent instanceof Assign) { Assign assign = (Assign) parent; /* The given name has to be one of the targets of this assignment */ for (exprType x : assign.targets) { if (x == variable) { return assign; } } } } return null; } private List<Name> findAllRelatedVariables(List<Name> variables, Name selectedVariable) { List<Name> relatedVariables = new LinkedList<Name>(); for (Name variable : variables) { if (variable.id.equals(selectedVariable.id)) { relatedVariables.add(variable); } } return relatedVariables; } private Name findSelectedVariable(ITextSelection selection, List<Name> variables) { int selectionOffset = selection.getOffset(); for (Name variable : variables) { int nodeLength = variable.id.length(); int nodeOffsetBegin = org.python.pydev.parser.visitors.NodeUtils.getOffset(info.getDocument(), variable); int nodeOffsetEnd = nodeOffsetBegin + nodeLength; if (selectionOffset >= nodeOffsetBegin && selectionOffset <= nodeOffsetEnd) { return variable; } } return null; } @Override public String getName() { return Messages.inlineLocalLabel; } public InlineLocalRequestProcessor getRequestProcessor() { return requestProcessor; } }