blob: 5b1217072465138f97a497e9f7c65e230b3855cc [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.debugger;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Processor;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
import com.intellij.xdebugger.stepping.XSmartStepIntoVariant;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyCallExpression;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
/**
* @author traff
*/
public class PySmartStepIntoHandler extends XSmartStepIntoHandler<PySmartStepIntoHandler.PySmartStepIntoVariant> {
private final XDebugSession mySession;
private PyDebugProcess myProcess;
public PySmartStepIntoHandler(final PyDebugProcess process) {
mySession = process.getSession();
myProcess = process;
}
@Override
@NotNull
public List<PySmartStepIntoVariant> computeSmartStepVariants(@NotNull XSourcePosition position) {
final Document document = FileDocumentManager.getInstance().getDocument(position.getFile());
final List<PySmartStepIntoVariant> variants = Lists.newArrayList();
final Set<PyCallExpression> visitedCalls = Sets.newHashSet();
final int line = position.getLine();
XDebuggerUtil.getInstance().iterateLine(mySession.getProject(), document, line, new Processor<PsiElement>() {
@Override
public boolean process(PsiElement psiElement) {
addVariants(document, line, psiElement, variants, visitedCalls);
return true;
}
});
return variants;
}
@Override
public void startStepInto(@NotNull PySmartStepIntoVariant smartStepIntoVariant) {
myProcess.startSmartStepInto(smartStepIntoVariant.getFunctionName());
}
@Override
public String getPopupTitle(@NotNull XSourcePosition position) {
return PyBundle.message("debug.popup.title.step.into.function");
}
private static void addVariants(Document document, int line, @Nullable PsiElement element,
List<PySmartStepIntoVariant> variants,
Set<PyCallExpression> visited) {
if (element == null) return;
final PyCallExpression expression = PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
if (expression != null &&
expression.getTextRange().getEndOffset() <= document.getLineEndOffset(line) &&
visited.add(expression)) {
addVariants(document, line, expression.getParent(), variants, visited);
PyExpression ref = expression.getCallee();
variants.add(new PySmartStepIntoVariant(ref));
}
}
public static class PySmartStepIntoVariant extends XSmartStepIntoVariant {
//private final String myFunctionName;
private final PyElement myElement;
public PySmartStepIntoVariant(PyElement element) {
myElement = element;
}
@Override
public String getText() {
return myElement.getText() + "()";
}
public String getFunctionName() {
String name = myElement.getName();
return name != null ? name : getText();
}
}
}