mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
cleanup
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface ConditionInstruction extends Instruction {
|
||||
boolean getResult();
|
||||
PsiElement getCondition();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface ControlFlow {
|
||||
Instruction[] getInstructions();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface ControlFlowOwner extends PyElement {
|
||||
ControlFlow getControlFlow();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface Instruction {
|
||||
@Nullable
|
||||
public PyElement getElement();
|
||||
|
||||
public Collection<Instruction> allSucc();
|
||||
|
||||
public Collection<Instruction> allPred();
|
||||
|
||||
String getElementPresentation();
|
||||
|
||||
public int num();
|
||||
}
|
||||
@@ -0,0 +1,523 @@
|
||||
package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.codeInsight.controlflow.impl.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
|
||||
// Here we store all the instructions
|
||||
private List<Instruction> myInstructions;
|
||||
|
||||
private Instruction myPrevInstruction;
|
||||
|
||||
// Here we store all the pending instructions with their scope
|
||||
private List<Pair<PsiElement, Instruction>> myPending;
|
||||
|
||||
private int myInstructionNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//// Control flow builder staff
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ControlFlow buildControlFlow(@NotNull final ControlFlowOwner owner) {
|
||||
myInstructions = new ArrayList<Instruction>();
|
||||
myPending = new ArrayList<Pair<PsiElement, Instruction>>();
|
||||
myInstructionNumber = 0;
|
||||
|
||||
// create start pseudo node
|
||||
startNode(null);
|
||||
|
||||
owner.acceptChildren(this);
|
||||
|
||||
// create end pseudo node and close all pending edges
|
||||
checkPending(startNode(null));
|
||||
|
||||
return new ControlFlowImpl(myInstructions.toArray(new Instruction[myInstructions.size()]));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Instruction findInstructionByElement(final PsiElement element) {
|
||||
for (int i = myInstructions.size() - 1; i >= 0; i--) {
|
||||
final Instruction instruction = myInstructions.get(i);
|
||||
if (element.equals(instruction.getElement())) {
|
||||
return instruction;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds edge between 2 edges
|
||||
*
|
||||
* @param beginInstruction Begin of new edge
|
||||
* @param endInstruction End of new edge
|
||||
*/
|
||||
private static void addEdge(final Instruction beginInstruction, final Instruction endInstruction) {
|
||||
if (beginInstruction == null || endInstruction == null) {
|
||||
return;
|
||||
}
|
||||
if (!beginInstruction.allSucc().contains(endInstruction)) {
|
||||
beginInstruction.allSucc().add(endInstruction);
|
||||
}
|
||||
|
||||
if (!endInstruction.allPred().contains(beginInstruction)) {
|
||||
endInstruction.allPred().add(beginInstruction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new node and set prev instruction pointing to this instruction
|
||||
*
|
||||
* @param instruction new instruction
|
||||
*/
|
||||
private void addNode(final Instruction instruction) {
|
||||
myInstructions.add(instruction);
|
||||
if (myPrevInstruction != null) {
|
||||
addEdge(myPrevInstruction, instruction);
|
||||
}
|
||||
myPrevInstruction = instruction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops control flow, used for break, next, redo
|
||||
*/
|
||||
private void flowAbrupted() {
|
||||
myPrevInstruction = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds pending edge in pendingScope
|
||||
*
|
||||
* @param pendingScope Scope for instruction
|
||||
* @param instruction "Last" pending instruction
|
||||
*/
|
||||
private void addPendingEdge(final PsiElement pendingScope, final Instruction instruction) {
|
||||
if (instruction == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
// another optimization! Place pending before first scope, not contained in pendingScope
|
||||
// the same logic is used in checkPending
|
||||
if (pendingScope != null) {
|
||||
for (; i < myPending.size(); i++) {
|
||||
final Pair<PsiElement, Instruction> pair = myPending.get(i);
|
||||
final PsiElement scope = pair.getFirst();
|
||||
if (scope == null) {
|
||||
continue;
|
||||
}
|
||||
if (!PsiTreeUtil.isAncestor(scope, pendingScope, true)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
myPending.add(i, Pair.create(pendingScope, instruction));
|
||||
}
|
||||
|
||||
private void checkPending(@NotNull final Instruction instruction) {
|
||||
final PsiElement element = instruction.getElement();
|
||||
if (element == null) {
|
||||
// if element is null (fake element, we just process all pending)
|
||||
for (Pair<PsiElement, Instruction> pair : myPending) {
|
||||
addEdge(pair.getSecond(), instruction);
|
||||
}
|
||||
myPending.clear();
|
||||
}
|
||||
else {
|
||||
// else we just all the pending with scope containing in element
|
||||
// reverse order is just an optimization
|
||||
for (int i = myPending.size() - 1; i >= 0; i--) {
|
||||
final Pair<PsiElement, Instruction> pair = myPending.get(i);
|
||||
final PsiElement scopeWhenToAdd = pair.getFirst();
|
||||
if (scopeWhenToAdd == null) {
|
||||
continue;
|
||||
}
|
||||
if (!PsiTreeUtil.isAncestor(scopeWhenToAdd, element, false)) {
|
||||
addEdge(pair.getSecond(), instruction);
|
||||
myPending.remove(i);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instruction for given element, and adds it to myInstructionsStack
|
||||
* Warning! Always call finishNode after startNode
|
||||
*
|
||||
* @param element Element to create instruction for
|
||||
* @return new instruction
|
||||
*/
|
||||
private Instruction startNode(final PyElement element) {
|
||||
final Instruction instruction = new InstructionImpl(element, myInstructionNumber++);
|
||||
addNode(instruction);
|
||||
checkPending(instruction);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates conditional instruction for given element, and adds it to myInstructionsStack
|
||||
* Warning! Always call finishNode after startNode
|
||||
*
|
||||
* @param element Element to create instruction for
|
||||
* @return new instruction
|
||||
*/
|
||||
private Instruction startConditionalNode(final PyElement element, final PyElement condition, final boolean result) {
|
||||
final ConditionInstruction instruction = new ConditionInstructionImpl(element, myInstructionNumber++, condition, result);
|
||||
addNode(instruction);
|
||||
checkPending(instruction);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyFunction(final PyFunction node) {
|
||||
// Stop here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyClass(final PyClass node) {
|
||||
// Stop here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyStatement(final PyStatement node) {
|
||||
startNode(node);
|
||||
super.visitPyStatement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyAssignmentStatement(final PyAssignmentStatement node) {
|
||||
startNode(node);
|
||||
final PyExpression value = node.getAssignedValue();
|
||||
if (value != null) {
|
||||
value.accept(this);
|
||||
}
|
||||
for (PyExpression expression : node.getTargets()) {
|
||||
expression.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyTargetExpression(final PyTargetExpression node) {
|
||||
final WriteInstruction instruction = new WriteInstructionImpl(node, node.getName(), myInstructionNumber++);
|
||||
addNode(instruction);
|
||||
checkPending(instruction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyNamedParameter(final PyNamedParameter node) {
|
||||
final WriteInstruction instruction = new WriteInstructionImpl(node, node.getName(), myInstructionNumber++);
|
||||
addNode(instruction);
|
||||
checkPending(instruction);
|
||||
}
|
||||
|
||||
private Instruction getPrevInstruction(final PyElement condition) {
|
||||
final Ref<Instruction> head = new Ref<Instruction>(myPrevInstruction);
|
||||
processPending(new PendingProcessor() {
|
||||
public void process(final PsiElement pendingScope, final Instruction instruction) {
|
||||
if (pendingScope != null && PsiTreeUtil.isAncestor(condition, pendingScope, false)) {
|
||||
head.set(instruction);
|
||||
}
|
||||
else {
|
||||
addPendingEdge(pendingScope, instruction);
|
||||
}
|
||||
}
|
||||
});
|
||||
return head.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyIfStatement(final PyIfStatement node) {
|
||||
startNode(node);
|
||||
final PyIfPart ifPart = node.getIfPart();
|
||||
PyExpression condition = ifPart.getCondition();
|
||||
if (condition != null) {
|
||||
condition.accept(this);
|
||||
}
|
||||
// Set the head as the last instruction of condition
|
||||
Instruction head = getPrevInstruction(condition);
|
||||
myPrevInstruction = head;
|
||||
final PyStatementList thenStatements = ifPart.getStatementList();
|
||||
if (thenStatements != null) {
|
||||
startConditionalNode(thenStatements, condition, true);
|
||||
thenStatements.accept(this);
|
||||
processPending(new PendingProcessor() {
|
||||
public void process(final PsiElement pendingScope, final Instruction instruction) {
|
||||
if (pendingScope != null && PsiTreeUtil.isAncestor(thenStatements, pendingScope, false)) {
|
||||
addPendingEdge(node, instruction);
|
||||
}
|
||||
else {
|
||||
addPendingEdge(pendingScope, instruction);
|
||||
}
|
||||
}
|
||||
});
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
for (PyIfPart part : node.getElifParts()) {
|
||||
// restore head
|
||||
myPrevInstruction = head;
|
||||
condition = part.getCondition();
|
||||
if (condition != null) {
|
||||
condition.accept(this);
|
||||
}
|
||||
// Set the head as the last instruction of condition
|
||||
head = getPrevInstruction(condition);
|
||||
myPrevInstruction = head;
|
||||
startConditionalNode(ifPart, condition, true);
|
||||
final PyStatementList statementList = part.getStatementList();
|
||||
if (statementList != null) {
|
||||
statementList.accept(this);
|
||||
}
|
||||
processPending(new PendingProcessor() {
|
||||
public void process(final PsiElement pendingScope, final Instruction instruction) {
|
||||
if (pendingScope != null && PsiTreeUtil.isAncestor(ifPart, pendingScope, false)) {
|
||||
addPendingEdge(node, instruction);
|
||||
}
|
||||
else {
|
||||
addPendingEdge(pendingScope, instruction);
|
||||
}
|
||||
}
|
||||
});
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
// restore head
|
||||
myPrevInstruction = head;
|
||||
final PyElsePart elseBranch = node.getElsePart();
|
||||
if (elseBranch != null) {
|
||||
startConditionalNode(elseBranch, condition, false);
|
||||
elseBranch.accept(this);
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyWhileStatement(final PyWhileStatement node) {
|
||||
final Instruction instruction = startNode(node);
|
||||
final PyWhilePart whilePart = node.getWhilePart();
|
||||
final PyExpression condition = whilePart.getCondition();
|
||||
if (condition != null) {
|
||||
condition.accept(this);
|
||||
}
|
||||
final Instruction head = getPrevInstruction(condition);
|
||||
myPrevInstruction = head;
|
||||
|
||||
// if condition was false
|
||||
final PyElsePart elsePart = node.getElsePart();
|
||||
if (elsePart == null) {
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
|
||||
final PyStatementList statementList = whilePart.getStatementList();
|
||||
if (statementList != null) {
|
||||
startConditionalNode(statementList, condition, true);
|
||||
statementList.accept(this);
|
||||
}
|
||||
if (myPrevInstruction != null) {
|
||||
addEdge(myPrevInstruction, instruction); //loop
|
||||
}
|
||||
// else part
|
||||
if (elsePart != null) {
|
||||
startConditionalNode(statementList, condition, false);
|
||||
elsePart.accept(this);
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
flowAbrupted();
|
||||
checkPending(instruction); //check for breaks targeted here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyForStatement(final PyForStatement node) {
|
||||
startNode(node);
|
||||
final PyForPart forPart = node.getForPart();
|
||||
final PyExpression source = forPart.getSource();
|
||||
if (source != null) {
|
||||
source.accept(this);
|
||||
}
|
||||
final Instruction head = myPrevInstruction;
|
||||
final PyElsePart elsePart = node.getElsePart();
|
||||
if (elsePart == null) {
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
|
||||
final PyStatementList list = forPart.getStatementList();
|
||||
if (list != null) {
|
||||
Instruction bodyInstruction = startNode(list);
|
||||
final PyExpression target = forPart.getTarget();
|
||||
if (target != null) {
|
||||
target.accept(this);
|
||||
}
|
||||
|
||||
list.accept(this);
|
||||
|
||||
if (myPrevInstruction != null) {
|
||||
addEdge(myPrevInstruction, bodyInstruction); //loop
|
||||
addPendingEdge(node, myPrevInstruction); // exit
|
||||
}
|
||||
}
|
||||
myPrevInstruction = head;
|
||||
if (elsePart != null) {
|
||||
elsePart.accept(this);
|
||||
addPendingEdge(node, myPrevInstruction); // exit
|
||||
}
|
||||
flowAbrupted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyBreakStatement(final PyBreakStatement node) {
|
||||
final Instruction breakInstruction = new InstructionImpl(node, myInstructionNumber++);
|
||||
addNode(breakInstruction);
|
||||
checkPending(breakInstruction);
|
||||
final PyLoopStatement loop = node.getLoopStatement();
|
||||
if (loop != null) {
|
||||
addPendingEdge(loop, myPrevInstruction);
|
||||
flowAbrupted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyContinueStatement(final PyContinueStatement node) {
|
||||
final Instruction nextInstruction = new InstructionImpl(node, myInstructionNumber++);
|
||||
addNode(nextInstruction);
|
||||
checkPending(nextInstruction);
|
||||
final PyLoopStatement loop = node.getLoop();
|
||||
if (loop != null) {
|
||||
final Instruction instruction = findInstructionByElement(loop);
|
||||
if (instruction != null) {
|
||||
addEdge(myPrevInstruction, instruction);
|
||||
flowAbrupted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyReturnStatement(final PyReturnStatement node) {
|
||||
final Instruction instruction = new InstructionImpl(node, myInstructionNumber++);
|
||||
addNode(instruction);
|
||||
checkPending(instruction);
|
||||
final PyExpression expression = node.getExpression();
|
||||
if (expression != null) {
|
||||
expression.accept(this);
|
||||
}
|
||||
// Here we process pending instructions!!!
|
||||
final List<Pair<PsiElement, Instruction>> pending = myPending;
|
||||
myPending = new ArrayList<Pair<PsiElement, Instruction>>();
|
||||
|
||||
for (Pair<PsiElement, Instruction> pair : pending) {
|
||||
final PsiElement pendingScope = pair.getFirst();
|
||||
if (pendingScope != null && PsiTreeUtil.isAncestor(node, pendingScope, false)) {
|
||||
final Instruction pendingInstruction = pair.getSecond();
|
||||
addPendingEdge(null, pendingInstruction);
|
||||
}
|
||||
else {
|
||||
myPending.add(pair);
|
||||
}
|
||||
}
|
||||
|
||||
addPendingEdge(null, myPrevInstruction);
|
||||
flowAbrupted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyTryExceptStatement(final PyTryExceptStatement node) {
|
||||
startNode(node);
|
||||
|
||||
// process body
|
||||
final PyTryPart tryPart = node.getTryPart();
|
||||
startNode(tryPart);
|
||||
tryPart.accept(this);
|
||||
final Instruction lastBlockInstruction = myPrevInstruction;
|
||||
|
||||
// Goto else block after execution, or exit
|
||||
final PyElsePart elsePart = node.getElsePart();
|
||||
if (elsePart != null) {
|
||||
startNode(elsePart);
|
||||
elsePart.accept(this);
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
} else {
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
|
||||
final ArrayList<Instruction> rescueInstructions = new ArrayList<Instruction>();
|
||||
for (PyExceptPart exceptPart : node.getExceptParts()) {
|
||||
myPrevInstruction = lastBlockInstruction;
|
||||
final Instruction rescueInstruction = startNode(exceptPart);
|
||||
rescueInstructions.add(rescueInstruction);
|
||||
exceptPart.accept(this);
|
||||
addPendingEdge(node, myPrevInstruction);
|
||||
}
|
||||
|
||||
final PyFinallyPart finallyPart = node.getFinallyPart();
|
||||
Instruction finallyInstruction = null;
|
||||
Instruction lastFinallyInstruction = null;
|
||||
if (finallyPart != null) {
|
||||
flowAbrupted();
|
||||
finallyInstruction = startNode(finallyPart);
|
||||
finallyPart.accept(this);
|
||||
lastFinallyInstruction = myPrevInstruction;
|
||||
addPendingEdge(finallyPart, lastFinallyInstruction);
|
||||
}
|
||||
final Ref<Instruction> finallyRef = new Ref<Instruction>(finallyInstruction);
|
||||
final Ref<Instruction> lastFinallyRef = new Ref<Instruction>(lastFinallyInstruction);
|
||||
processPending(new PendingProcessor() {
|
||||
public void process(final PsiElement pendingScope, final Instruction instruction) {
|
||||
final PyElement pendingElement = instruction.getElement();
|
||||
|
||||
// handle raise instructions inside compound statement
|
||||
if (pendingElement instanceof PyRaiseStatement &&
|
||||
PsiTreeUtil.isAncestor(tryPart, pendingElement, false)){
|
||||
for (Instruction rescueInstruction : rescueInstructions) {
|
||||
addEdge(instruction, rescueInstruction);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// handle return pending instructions inside body if ensure block exists
|
||||
if (pendingElement instanceof PyReturnStatement && !finallyRef.isNull() &&
|
||||
PsiTreeUtil.isAncestor(node, pendingElement, false)) {
|
||||
addEdge(instruction, finallyRef.get());
|
||||
addPendingEdge(null, lastFinallyRef.get());
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle pending instructions inside body with ensure block
|
||||
if (pendingElement != null && finallyPart!=null && pendingScope !=finallyPart &&
|
||||
PsiTreeUtil.isAncestor(node, pendingElement, false)) {
|
||||
addEdge(instruction, finallyRef.get());
|
||||
return;
|
||||
}
|
||||
addPendingEdge(pendingScope, instruction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyListCompExpression(final PyListCompExpression node) {
|
||||
super.visitPyListCompExpression(node);
|
||||
}
|
||||
|
||||
|
||||
private static interface PendingProcessor {
|
||||
void process(PsiElement pendingScope, Instruction instruction);
|
||||
}
|
||||
|
||||
private void processPending(final PendingProcessor processor) {
|
||||
final List<Pair<PsiElement, Instruction>> pending = myPending;
|
||||
myPending = new ArrayList<Pair<PsiElement, Instruction>>();
|
||||
for (Pair<PsiElement, Instruction> pair : pending) {
|
||||
processor.process(pair.getFirst(), pair.getSecond());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface WriteInstruction extends Instruction {
|
||||
String getName();
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package com.jetbrains.python.psi;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.jetbrains.python.psi.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.psi.stubs.PyClassStub;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -6,7 +6,7 @@ package com.jetbrains.python.psi;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.psi.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.jetbrains.python.psi;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.jetbrains.python.psi.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowOwner;
|
||||
import com.jetbrains.python.psi.stubs.PyFunctionStub;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -13,8 +13,8 @@ import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonDosStringFinder;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.psi.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.codeInsight.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveUtil;
|
||||
import com.jetbrains.python.psi.resolve.VariantsProcessor;
|
||||
import com.jetbrains.python.psi.stubs.PyClassStub;
|
||||
|
||||
@@ -17,8 +17,8 @@ import com.jetbrains.python.PythonDosStringFinder;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.psi.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.codeInsight.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveUtil;
|
||||
import com.jetbrains.python.psi.resolve.ResolveProcessor;
|
||||
import com.jetbrains.python.psi.types.PyModuleType;
|
||||
|
||||
@@ -28,8 +28,8 @@ import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonDosStringFinder;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.psi.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.codeInsight.controlflow.PyControlFlowBuilder;
|
||||
import com.jetbrains.python.psi.stubs.PyClassStub;
|
||||
import com.jetbrains.python.psi.stubs.PyFunctionStub;
|
||||
import com.jetbrains.python.toolbox.SingleIterable;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
while foo
|
||||
if condition
|
||||
break
|
||||
puts "Hello"
|
||||
@@ -0,0 +1,9 @@
|
||||
0(1) element: null
|
||||
1(2,8) element: PyWhileStatement
|
||||
2(3) element: PyStatementList. Condition: foo:true
|
||||
3(4,6) element: PyIfStatement
|
||||
4(5) element: PyStatementList. Condition: condition:true
|
||||
5(8) element: PyBreakStatement
|
||||
6(7) element: PyExpressionStatement
|
||||
7(1) element: PyExpressionStatement
|
||||
8() element: null
|
||||
@@ -0,0 +1,4 @@
|
||||
while foo
|
||||
if condition
|
||||
continue
|
||||
puts "Hello"
|
||||
@@ -0,0 +1,9 @@
|
||||
0(1) element: null
|
||||
1(2,8) element: PyWhileStatement
|
||||
2(3) element: PyStatementList. Condition: foo:true
|
||||
3(4,6) element: PyIfStatement
|
||||
4(5) element: PyStatementList. Condition: condition:true
|
||||
5(1) element: PyContinueStatement
|
||||
6(7) element: PyExpressionStatement
|
||||
7(1) element: PyExpressionStatement
|
||||
8() element: null
|
||||
@@ -0,0 +1,2 @@
|
||||
aaa = 12
|
||||
print(aaa)
|
||||
@@ -0,0 +1,5 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyAssignmentStatement
|
||||
2(3) WRITE ACCESS: aaa
|
||||
3(4) element: PyPrintStatement
|
||||
4() element: null
|
||||
@@ -0,0 +1,4 @@
|
||||
for i in range(10)
|
||||
print(i)
|
||||
else
|
||||
print "Something went wrong"
|
||||
@@ -0,0 +1,7 @@
|
||||
0(1) element: null
|
||||
1(2,5) element: PyForStatement
|
||||
2(3) element: PyStatementList
|
||||
3(4) WRITE ACCESS: i
|
||||
4(2,6) element: PyPrintStatement
|
||||
5(6) element: PyPrintStatement
|
||||
6() element: null
|
||||
@@ -0,0 +1,14 @@
|
||||
def help(object, spacing=10, collapse=1):
|
||||
"""Выводит методы и строки документации.
|
||||
|
||||
В качестве аргумента может использоваться модуль, класс, список, словарь
|
||||
или строка."""
|
||||
methodList = [method for method in dir(object) if callable(getattr(object, method))]
|
||||
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
|
||||
print "\n".join(["%s %s" %
|
||||
(method.ljust(spacing),
|
||||
processFunc(str(getattr(object, method).__doc__)))
|
||||
for method in methodList])
|
||||
|
||||
if __name__ == "__main__":
|
||||
print help.__doc__
|
||||
@@ -0,0 +1,15 @@
|
||||
0(1) element: null
|
||||
1(2) WRITE ACCESS: object
|
||||
2(3) WRITE ACCESS: spacing
|
||||
3(4) WRITE ACCESS: collapse
|
||||
4(5) element: PyExpressionStatement
|
||||
5(6) element: PyAssignmentStatement
|
||||
6(7) WRITE ACCESS: method
|
||||
7(8) WRITE ACCESS: methodList
|
||||
8(9) element: PyAssignmentStatement
|
||||
9(10) WRITE ACCESS: s
|
||||
10(11) WRITE ACCESS: s
|
||||
11(12) WRITE ACCESS: processFunc
|
||||
12(13) element: PyPrintStatement
|
||||
13(14) WRITE ACCESS: method
|
||||
14() element: null
|
||||
@@ -0,0 +1,19 @@
|
||||
if 0:
|
||||
pass
|
||||
|
||||
if 1:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
if 2:
|
||||
pass
|
||||
elif 3:
|
||||
pass
|
||||
|
||||
if 4:
|
||||
pass
|
||||
elif 5:
|
||||
pass
|
||||
else:
|
||||
1
|
||||
@@ -0,0 +1,15 @@
|
||||
0(1) element: null
|
||||
1(2,3) element: PyIfStatement
|
||||
2(3) element: PyStatementList. Condition: 0:true
|
||||
3(4,5) element: PyIfStatement
|
||||
4(6) element: PyStatementList. Condition: 1:true
|
||||
5(6) element: PyElsePart. Condition: 1:false
|
||||
6(7,8,9) element: PyIfStatement
|
||||
7(9) element: PyStatementList. Condition: 2:true
|
||||
8(9) element: PyIfPartIf. Condition: 3:true
|
||||
9(10,11,12) element: PyIfStatement
|
||||
10(14) element: PyStatementList. Condition: 4:true
|
||||
11(14) element: PyIfPartIf. Condition: 5:true
|
||||
12(13) element: PyElsePart. Condition: 5:false
|
||||
13(14) element: PyExpressionStatement
|
||||
14() element: null
|
||||
@@ -0,0 +1 @@
|
||||
[k for k, v in params.items()]
|
||||
@@ -0,0 +1,4 @@
|
||||
while foo
|
||||
if condition
|
||||
return "Result"
|
||||
puts "Hello"
|
||||
@@ -0,0 +1,9 @@
|
||||
0(1) element: null
|
||||
1(2,8) element: PyWhileStatement
|
||||
2(3) element: PyStatementList. Condition: foo:true
|
||||
3(4,6) element: PyIfStatement
|
||||
4(5) element: PyStatementList. Condition: condition:true
|
||||
5(8) element: PyReturnStatement
|
||||
6(7) element: PyExpressionStatement
|
||||
7(1) element: PyExpressionStatement
|
||||
8() element: null
|
||||
@@ -0,0 +1,13 @@
|
||||
import sys
|
||||
|
||||
try:
|
||||
f = open('myfile.txt')
|
||||
s = f.readline()
|
||||
i = int(s.strip())
|
||||
except IOError as (errno, strerror):
|
||||
print "I/O error({0}): {1}".format(errno, strerror)
|
||||
except ValueError:
|
||||
print "Could not convert data to an integer."
|
||||
except:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
raise
|
||||
@@ -0,0 +1,20 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyImportStatement
|
||||
2(3) element: PyTryExceptStatement
|
||||
3(4) element: PyTryPart
|
||||
4(5) element: PyAssignmentStatement
|
||||
5(6) WRITE ACCESS: f
|
||||
6(7) element: PyAssignmentStatement
|
||||
7(8) WRITE ACCESS: s
|
||||
8(9) element: PyAssignmentStatement
|
||||
9(10,14,16,19) WRITE ACCESS: i
|
||||
10(11) element: PyExceptPart
|
||||
11(12) WRITE ACCESS: errno
|
||||
12(13) WRITE ACCESS: strerror
|
||||
13(19) element: PyPrintStatement
|
||||
14(15) element: PyExceptPart
|
||||
15(19) element: PyPrintStatement
|
||||
16(17) element: PyExceptPart
|
||||
17(18) element: PyPrintStatement
|
||||
18(19) element: PyRaiseStatement
|
||||
19() element: null
|
||||
@@ -0,0 +1,4 @@
|
||||
while condition
|
||||
print("Alloha!")
|
||||
else:
|
||||
print("Bye")
|
||||
@@ -0,0 +1,7 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyWhileStatement
|
||||
2(3) element: PyStatementList. Condition: condition:true
|
||||
3(1,4) element: PyPrintStatement
|
||||
4(5) element: PyStatementList. Condition: condition:false
|
||||
5(6) element: PyPrintStatement
|
||||
6() element: null
|
||||
@@ -7,8 +7,8 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.python.fixtures.LightMarkedTestCase;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.psi.controlflow.Instruction;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlow;
|
||||
import com.jetbrains.python.codeInsight.controlflow.Instruction;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -19,7 +19,7 @@ import java.io.IOException;
|
||||
public class PyControlFlowBuilderTest extends LightMarkedTestCase {
|
||||
|
||||
public String getTestDataPath() {
|
||||
return PythonTestUtil.getTestDataPath() + "/psi/controlflow/";
|
||||
return PythonTestUtil.getTestDataPath() + "/codeInsight/controlflow/";
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user