Revert "Revert "Merge branch 'master' of git.labs.intellij.net:idea/ultimate""

This reverts commit 3a2ad1f6c248ce02e860be14b796981de7ccfeee.
This commit is contained in:
Dmitry Trofimov
2011-02-04 17:17:18 +03:00
parent 819731653c
commit 67bcf88cbd
25 changed files with 193 additions and 49 deletions

View File

@@ -26,7 +26,7 @@ if [ -z "$PYCHARM_JDK" ]; then
fi
if [ -z "$PYCHARM_JDK" ]; then
echo ERROR: cannot start PyCharm.
echo No JDK found to run PyCharm. Please validate either PYCHARM_JDK, JDK_HOME or JAVA_HOME points to valid JDK installation.
echo No JDK found to run PyCharm. Please validate either PYCHARM_JDK, JDK_HOME or JAVA_HOME environment variable points to valid JDK installation.
echo
echo Press Enter to continue.
read IGNORE
@@ -47,7 +47,7 @@ if [ $OPEN_JDK -eq 0 ]; then
echo THIS IS STRICTLY UNSUPPORTED DUE TO KNOWN PERFORMANCE AND GRAPHICS PROBLEMS
echo
echo NOTE: If you have both Sun JDK and OpenJDK installed
echo please validate either PYCHARM_JDK or JDK_HOME points to valid Sun JDK installation
echo please validate either PYCHARM_JDK or JDK_HOME environment variable points to valid Sun JDK installation
echo
echo Press Enter to continue.
read IGNORE

View File

@@ -280,7 +280,7 @@ def build_searchable_options() {
ant.copy(file: "$home/build/idea.license", todir: paths.ideaSystem)
ant.copy(file: "$home/build/pycharm.license", todir: paths.ideaSystem)
ant.java(classname: "com.intellij.idea.Main", fork: "true") {
jvmarg(line: "-ea -Xmx250m -Didea.home.path=$home -Didea.system.path=${paths.ideaSystem} -Didea.config.path=${paths.ideaConfig} -Didea.platform.prefix=Python")
jvmarg(line: "-ea -Xmx250m -Didea.home.path=$home -Didea.system.path=${paths.ideaSystem} -Didea.config.path=${paths.ideaConfig} -Didea.platform.prefix=Python -Didea.no.jre.check=true")
jvmarg(value: "-Xbootclasspath/a:${boot.output}")
arg(line: "traverseUI ${dest_dir}/searchableOptions.xml")

View File

@@ -4,6 +4,8 @@ settings_file = os.getenv('PYCHARM_DJANGO_SETTINGS_MODULE')
if not settings_file:
settings_file = 'settings'
print ("Importing Django settings module " + settings_file)
try:
settings_module = __import__(settings_file)
@@ -19,4 +21,3 @@ except ImportError:
TEST_RUNNER = 'pycharm.django_test_runner.run_tests'
print ("pycharm django settings imported") # XXX

View File

@@ -69,8 +69,10 @@ class TeamcityTestResult(TestResult):
error_value = err[1][0]
if error_value.startswith("'") or error_value.startswith('"'):
first = self.find_first(err[1][0])
second = self.find_second(err[1][0])
# let's unescape strings to show sexy multiline diff in PyCharm.
# By default all caret return chars are escaped by testing framework
first = self._unescape(self.find_first(err[1][0]))
second = self._unescape(self.find_second(err[1][0]))
else:
first = second = ""
err = self.formatErr(err)
@@ -118,6 +120,9 @@ class TeamcityTestResult(TestResult):
self.messages.testSuiteFinished(self.current_suite)
self.current_suite = None
def _unescape(self, text):
return text.decode('string_escape')
class TeamcityTestRunner:
def __init__(self, stream=sys.stdout):
self.stream = stream

View File

@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="sass" scope="RUNTIME" />
<orderEntry type="module" module-name="dom-impl" scope="RUNTIME" />
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="module" module-name="colorSchemes" scope="RUNTIME" />
</component>
</module>

View File

@@ -1,6 +1,6 @@
<component>
<!-- <version name="IntelliJ IDEA" major="6" minor="0.2 Beta"/> -->
<version codename="1.1 Early Access Preview" major="1" minor="0" eap="true" update-channel="pycharm"/>
<version codename="1.2 Early Access Preview" major="1" minor="2" eap="true" update-channel="pycharm"/>
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
<logo url="/pycharm_logo.png" textcolor="B7C9B5"/>
<about url="/pycharm_about.png"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -277,6 +277,9 @@
<moduleService serviceInterface="com.jetbrains.django.model.TemplateManager"
serviceImplementation="com.jetbrains.django.model.TemplateManager"/>
<projectService serviceInterface="com.jetbrains.django.model.DjangoTagLibrary"
serviceImplementation="com.jetbrains.django.model.DjangoTagLibrary"/>
<facetType implementation="com.jetbrains.django.facet.DjangoFacetType"/>
<codeInsight.lineMarkerProvider language="DjangoTemplate" implementationClass="com.jetbrains.django.annotator.ViewLineMarkerProvider"/>

View File

@@ -204,8 +204,9 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
condition.accept(assertionEvaluator);
}
// Set the head as the last instruction of condition
Instruction head = getPrevInstruction(condition);
myBuilder.prevInstruction = head;
PyElement lastCondition = condition;
Instruction lastBranchingPoint = getPrevInstruction(condition);
myBuilder.prevInstruction = lastBranchingPoint;
final PyStatementList thenStatements = ifPart.getStatementList();
if (thenStatements != null) {
myBuilder.startConditionalNode(thenStatements, condition, true);
@@ -223,24 +224,26 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
});
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
}
for (PyIfPart part : node.getElifParts()) {
// restore head
myBuilder.prevInstruction = head;
for (final PyIfPart part : node.getElifParts()) {
// Set the head as the false branch
myBuilder.prevInstruction = lastBranchingPoint;
myBuilder.startConditionalNode(part, lastCondition, false);
condition = part.getCondition();
if (condition != null) {
lastCondition = condition;
lastBranchingPoint = getPrevInstruction(lastCondition);
condition.accept(this);
}
// Set the head as the last instruction of condition
head = getPrevInstruction(condition);
myBuilder.prevInstruction = head;
myBuilder.startConditionalNode(ifPart, condition, true);
myBuilder.prevInstruction = getPrevInstruction(lastCondition);
myBuilder.startConditionalNode(part, lastCondition, true);
final PyStatementList statementList = part.getStatementList();
if (statementList != null) {
statementList.accept(this);
}
myBuilder.processPending(new ControlFlowBuilder.PendingProcessor() {
public void process(final PsiElement pendingScope, final Instruction instruction) {
if (pendingScope != null && PsiTreeUtil.isAncestor(ifPart, pendingScope, false)) {
if (pendingScope != null && PsiTreeUtil.isAncestor(part, pendingScope, false)) {
myBuilder.addPendingEdge(node, instruction);
}
else {
@@ -250,15 +253,16 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
});
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
}
// restore head
myBuilder.prevInstruction = head;
final PyElsePart elseBranch = node.getElsePart();
if (elseBranch != null) {
myBuilder.startConditionalNode(elseBranch, condition, false);
// Set the head as the false branch
myBuilder.prevInstruction = lastBranchingPoint;
myBuilder.startConditionalNode(elseBranch, lastCondition, false);
elseBranch.accept(this);
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
} else {
myBuilder.addPendingEdge(node, lastBranchingPoint);
}
}
@Override

View File

@@ -1,5 +1,6 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,6 +30,17 @@ public interface PyCallExpression extends PyExpression {
@NotNull
PyExpression[] getArguments();
/**
* If the list of arguments has at least {@code index} elements and the index'th element is of type argClass,
* returns it. Otherwise, returns null.
*
* @param index argument index
* @param argClass argument expected type
* @return the argument or null
*/
@Nullable
<T extends PsiElement> T getArgument(int index, Class<T> argClass);
void addArgument(PyExpression expression);
/**
@@ -61,9 +73,10 @@ public interface PyCallExpression extends PyExpression {
/**
* Method-oriented constructor.
* @param function the method (or any other callable, but why bother then).
* @param flags result of decorators or wrapping.
* @param offset implicit argument offset; parameters up to this are implicitly filled in the call.
*
* @param function the method (or any other callable, but why bother then).
* @param flags result of decorators or wrapping.
* @param offset implicit argument offset; parameters up to this are implicitly filled in the call.
* @param implicitlyResolved value for {@link #isImplicitlyResolved()}
*/
public PyMarkedCallee(@NotNull Callable function, EnumSet<PyFunction.Flag> flags, int offset, boolean implicitlyResolved) {
@@ -77,7 +90,7 @@ public interface PyCallExpression extends PyExpression {
myCallable = callable;
myFlags = EnumSet.noneOf(PyFunction.Flag.class);
myImplicitOffset = 0;
myImplicitlyResolved = implicitlyResolved;
myImplicitlyResolved = implicitlyResolved;
}
public Callable getCallable() {
@@ -90,8 +103,8 @@ public interface PyCallExpression extends PyExpression {
/**
* @return number of implicitly passed positional parameters; 0 means no parameters are passed implicitly.
* Note that a <tt>*args</tt> is never marked as passed implicitly.
* E.g. for a function like <tt>foo(a, b, *args)</tt> always holds <tt>getImplicitOffset() < 2</tt>.
* Note that a <tt>*args</tt> is never marked as passed implicitly.
* E.g. for a function like <tt>foo(a, b, *args)</tt> always holds <tt>getImplicitOffset() < 2</tt>.
*/
public int getImplicitOffset() {
return myImplicitOffset;

View File

@@ -47,6 +47,12 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
return argList != null ? argList.getArguments() : PyExpression.EMPTY_ARRAY;
}
@Override
public <T extends PsiElement> T getArgument(int index, Class<T> argClass) {
PyExpression[] args = getArguments();
return args.length >= index && argClass.isInstance(args[index]) ? argClass.cast(args[index]) : null;
}
public void addArgument(PyExpression expression) {
PyCallExpressionHelper.addArgument(this, expression);
}
@@ -56,7 +62,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
}
public boolean isCalleeText(@NotNull String... nameCandidates) {
return PyCallExpressionHelper.isCalleeText(this, nameCandidates);
return PyCallExpressionHelper.isCalleeText(this, nameCandidates);
}
@Override
@@ -100,7 +106,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
if (target instanceof Callable) {
final Callable callable = (Callable)target;
if (context.allowReturnTypes()) {
return callable.getReturnType(context, (PyReferenceExpression) callee);
return callable.getReturnType(context, (PyReferenceExpression)callee);
}
if (callable instanceof PyFunction) {
final PyType docStringType = ((PyFunction)callable).getReturnTypeFromDocString();
@@ -118,7 +124,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
else {
final PyType type = context.getType(callee);
if (type instanceof PyClassType) {
PyClassType classType = (PyClassType) type;
PyClassType classType = (PyClassType)type;
if (classType.isDefinition()) {
return new PyClassType(classType.getPyClass(), false);
}
@@ -151,7 +157,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
final PsiElement element = qRef == null ? null : qRef.resolve();
if (element instanceof PyParameter) {
final PyParameterList parameterList = PsiTreeUtil.getParentOfType(element, PyParameterList.class);
if (parameterList != null && element == parameterList.getParameters() [0]) {
if (parameterList != null && element == parameterList.getParameters()[0]) {
return getSuperCallType(context, containingClass, args[1]);
}
}
@@ -201,7 +207,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
final PyClass[] supers = pyClass.getSuperClasses();
if (supers.length > 0) {
if (supers.length == 1) {
return new PyClassType(supers [0], false);
return new PyClassType(supers[0], false);
}
List<PyType> superTypes = new ArrayList<PyType>();
for (PyClass aSuper : supers) {

View File

@@ -9,7 +9,6 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
import com.jetbrains.python.psi.stubs.PyDecoratorStub;
import com.jetbrains.python.psi.PyDecorator;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NonNls;
@@ -37,7 +36,7 @@ public class PyDecoratorImpl extends PyPresentableElementImpl<PyDecoratorStub> i
@Override
public String getName() {
final PyQualifiedName qname = getQualifiedName();
return qname != null? qname.getLastComponent() : null;
return qname != null ? qname.getLastComponent() : null;
}
@Nullable
@@ -101,6 +100,12 @@ public class PyDecoratorImpl extends PyPresentableElementImpl<PyDecoratorStub> i
return argList != null ? argList.getArguments() : PyExpression.EMPTY_ARRAY;
}
@Override
public <T extends PsiElement> T getArgument(int index, Class<T> argClass) {
PyExpression[] args = getArguments();
return args.length >= index && argClass.isInstance(args[index]) ? argClass.cast(args[index]) : null;
}
public void addArgument(PyExpression expression) {
PyCallExpressionHelper.addArgument(this, expression);
}
@@ -108,7 +113,7 @@ public class PyDecoratorImpl extends PyPresentableElementImpl<PyDecoratorStub> i
public PyMarkedCallee resolveCallee(TypeEvalContext context) {
PyMarkedCallee callee = PyCallExpressionHelper.resolveCallee(this, context);
if (callee == null) return null;
if (! hasArgumentList()) {
if (!hasArgumentList()) {
// NOTE: that +1 thing looks fishy
callee = new PyMarkedCallee(callee.getCallable(), callee.getFlags(), callee.getImplicitOffset() + 1, callee.isImplicitlyResolved());
}
@@ -132,7 +137,9 @@ public class PyDecoratorImpl extends PyPresentableElementImpl<PyDecoratorStub> i
node.replaceChild(name_node, nameElement);
return this;
}
else throw new IncorrectOperationException("No name node");
else {
throw new IncorrectOperationException("No name node");
}
}
// TODO: create a custom version of public PyType getType()

View File

@@ -197,12 +197,12 @@ public class PyClassRefactoringUtil {
}
private static void rememberNamedReferences(final List<PyFunction> methods) {
for (PyFunction method : methods) {
for (final PyFunction method : methods) {
method.acceptChildren(new PyRecursiveElementVisitor() {
@Override
public void visitPyReferenceExpression(PyReferenceExpression node) {
super.visitPyReferenceExpression(node);
rememberReference(node);
rememberReference(node, method);
}
});
}
@@ -210,13 +210,13 @@ public class PyClassRefactoringUtil {
private static final Key<PsiNamedElement> ENCODED_IMPORT = Key.create("PyEncodedImport");
private static void rememberReference(PyReferenceExpression node) {
private static void rememberReference(PyReferenceExpression node, PyFunction method) {
// we will remember reference in deepest node
if (node.getQualifier() instanceof PyReferenceExpression) return;
final PsiPolyVariantReference ref = node.getReference();
final PsiElement target = ref.resolve();
if (target instanceof PsiNamedElement) {
if (target instanceof PsiNamedElement && !PsiTreeUtil.isAncestor(method, target, false)) {
node.putCopyableUserData(ENCODED_IMPORT, (PsiNamedElement)target);
}
}

View File

@@ -4,12 +4,14 @@
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
6(7,8) element: PyIfStatement
7(10) element: PyStatementList. Condition: 2:true
8(9,10) element: PyIfPartElif. Condition: 2:false
9(10) element: PyIfPartElif. Condition: 3:true
10(11,12) element: PyIfStatement
11(16) element: PyStatementList. Condition: 4:true
12(13,14) element: PyIfPartElif. Condition: 4:false
13(16) element: PyIfPartElif. Condition: 5:true
14(15) element: PyElsePart. Condition: 5:false
15(16) element: PyExpressionStatement
16() element: null

View File

@@ -0,0 +1,13 @@
var = 1
if a == b:
var = 2
elif aa == bb:
bbb = same_changet_expression
if bbb:
var = 3 # <--- this highlight bug (unused variable)
else:
var = 4
return {'variable': var}

View File

@@ -0,0 +1,27 @@
0(1) element: null
1(2) element: PyAssignmentStatement
2(3) WRITE ACCESS: var
3(4) element: PyIfStatement
4(5) READ ACCESS: a
5(6,9) READ ACCESS: b
6(7) element: PyStatementList. Condition: a == b:true
7(8) element: PyAssignmentStatement
8(24) WRITE ACCESS: var
9(10,21) element: PyIfPartElif. Condition: a == b:false
10(11) READ ACCESS: aa
11(12) READ ACCESS: bb
12(13) element: PyIfPartElif. Condition: aa == bb:true
13(14) element: PyAssignmentStatement
14(15) READ ACCESS: same_changet_expression
15(16) WRITE ACCESS: bbb
16(17) element: PyIfStatement
17(18,24) READ ACCESS: bbb
18(19) element: PyStatementList. Condition: bbb:true
19(20) element: PyAssignmentStatement
20(24) WRITE ACCESS: var
21(22) element: PyElsePart. Condition: aa == bb:false
22(23) element: PyAssignmentStatement
23(24) WRITE ACCESS: var
24(25) element: PyReturnStatement
25(26) READ ACCESS: var
26() element: null

View File

@@ -0,0 +1,9 @@
from SuperClass import SuperClass
from sys import argv
class AnyClass(SuperClass):
def this_should_be_in_super(self, some_argument):
if not self.args:
self.args = argv
self.argument = some_argument

View File

@@ -0,0 +1,10 @@
from sys import argv
class SuperClass(object):
def __init__(self):
pass
def this_should_be_in_super(self, some_argument):
if not self.args:
self.args = argv
self.argument = some_argument

View File

@@ -0,0 +1,5 @@
from sys import argv
class SuperClass(object):
def __init__(self):
pass

View File

@@ -0,0 +1,5 @@
from SuperClass import SuperClass
class AnyClass(SuperClass):
def this_should_be_in_super(self, some_argument):
self.argument = some_argument

View File

@@ -0,0 +1,6 @@
class SuperClass(object):
def __init__(self):
pass
def this_should_be_in_super(self, some_argument):
self.argument = some_argument

View File

@@ -0,0 +1,3 @@
class SuperClass(object):
def __init__(self):
pass

View File

@@ -144,6 +144,10 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase {
doTest();
}
public void testManyIfs() throws Exception {
doTest();
}
public void testQualifiedSelfReference() throws Exception {
final String testName = getTestName(false).toLowerCase();
configureByFile(testName + ".py");

View File

@@ -30,13 +30,33 @@ public class PyPullUpTest extends PyClassRefactoringTest {
doHelperTest("Boo", ".boo", "Foo");
}
public void testMultiFile() { // PY-2810
doMultiFileTest();
}
public void testDuplicateImport() { // PY-2810
doMultiFileTest();
}
private void doMultiFileTest() {
String baseName = "refactoring/pullup/" + getTestName(true) + "/";
myFixture.copyFileToProject(baseName + "Class.py", "Class.py");
myFixture.copyFileToProject(baseName + "SuperClass.py", "SuperClass.py");
doPullUp("AnyClass", ".this_should_be_in_super", "SuperClass");
myFixture.checkResultByFile("SuperClass.py", "/" + baseName + "/SuperClass.after.py", true);
}
private void doHelperTest(final String className, final String memberName, final String superClassName) {
String baseName = "/refactoring/pullup/" + getTestName(true);
myFixture.configureByFile(baseName + ".py");
doPullUp(className, memberName, superClassName);
myFixture.checkResultByFile(baseName + ".after.py");
}
private void doPullUp(String className, String memberName, String superClassName) {
final PyClass clazz = findClass(className);
final PyElement member = findMember(className, memberName);
final PyClass superClass = findClass(superClassName);
PyPullUpHelper.pullUp(clazz, Collections.singleton(new PyMemberInfo(member)), superClass);
myFixture.checkResultByFile(baseName + ".after.py");
}
}