mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'python-fixes'
This commit is contained in:
@@ -139,9 +139,6 @@ public class PyCodeFragmentBuilder extends PyRecursiveElementVisitor {
|
||||
}
|
||||
// If declaration is before we look for modifications inside
|
||||
if (pos == Position.BEFORE) {
|
||||
if (!isTopLevel(element)) {
|
||||
inElements.add(name);
|
||||
}
|
||||
final List<PyElement> list = modifiedInsideMap.get(name);
|
||||
boolean modificationSeen = false;
|
||||
if (list != null) {
|
||||
@@ -154,6 +151,9 @@ public class PyCodeFragmentBuilder extends PyRecursiveElementVisitor {
|
||||
}
|
||||
}
|
||||
if (modificationSeen) {
|
||||
if (!isTopLevel(element)) {
|
||||
inElements.add(name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ __builtin__.locals = \
|
||||
:rtype: dict of (bytes, object)
|
||||
|
||||
__builtin__.map = \
|
||||
:type function: collections.Callable \n\
|
||||
:type function: collections.Callable or None \n\
|
||||
:type sequence: collections.Iterable \n\
|
||||
:rtype: list \n\
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.regex.Pattern;
|
||||
public class PyRequirement {
|
||||
private static final Pattern NAME = Pattern.compile("\\s*(\\w(\\w|[-.])*)\\s*(.*)");
|
||||
private static final Pattern VERSION_SPEC = Pattern.compile("\\s*(<=?|>=?|==|!=)\\s*((\\w|[-.])+)");
|
||||
private static final Pattern EDITABLE_EGG = Pattern.compile("\\s*-e\\s+([^#]*)#egg=(.*)");
|
||||
private static final Pattern EDITABLE_EGG = Pattern.compile("\\s*(-e)?\\s*([^#]*)#egg=(.*)");
|
||||
private static final Pattern RECURSIVE_REQUIREMENT = Pattern.compile("\\s*-r\\s+(.*)");
|
||||
private static final Pattern NAME_VERSION = Pattern.compile("\\s*(\\w(\\w|[.])*)-((\\w|[-.])+)");
|
||||
|
||||
@@ -119,6 +119,7 @@ public class PyRequirement {
|
||||
@NotNull private final String myName;
|
||||
@NotNull private final List<VersionSpec> myVersionSpecs;
|
||||
@Nullable private final String myURL;
|
||||
private final boolean myEditable;
|
||||
|
||||
public static final Comparator<String> VERSION_COMPARATOR = new Comparator<String>() {
|
||||
@Override
|
||||
@@ -171,6 +172,14 @@ public class PyRequirement {
|
||||
}
|
||||
results.add(component);
|
||||
}
|
||||
for (int i = results.size() - 1; i > 0; i--) {
|
||||
if ("00000000".equals(results.get(i))) {
|
||||
results.remove(i);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
results.add("*final");
|
||||
return results;
|
||||
}
|
||||
@@ -188,17 +197,19 @@ public class PyRequirement {
|
||||
myName = name;
|
||||
myVersionSpecs = versionSpecs;
|
||||
myURL = null;
|
||||
myEditable = false;
|
||||
}
|
||||
|
||||
public PyRequirement(@NotNull String name, @Nullable String version, @NotNull String url) {
|
||||
public PyRequirement(@NotNull String name, @Nullable String version, @NotNull String url, boolean editable) {
|
||||
myName = name;
|
||||
if (version != null) {
|
||||
myVersionSpecs = Collections.singletonList(new VersionSpec(Relation.GTE, version));
|
||||
myVersionSpecs = Collections.singletonList(new VersionSpec(Relation.EQ, version));
|
||||
}
|
||||
else {
|
||||
myVersionSpecs = Collections.emptyList();
|
||||
}
|
||||
myURL = url;
|
||||
myEditable = editable;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -216,11 +227,13 @@ public class PyRequirement {
|
||||
|
||||
@NotNull
|
||||
public List<String> toOptions() {
|
||||
final List<String> results = new ArrayList<String>();
|
||||
if (myEditable) {
|
||||
results.add("-e");
|
||||
}
|
||||
if (myURL != null) {
|
||||
final int size = myVersionSpecs.size();
|
||||
assert size <= 1;
|
||||
final List<String> results = new ArrayList<String>();
|
||||
results.add("-e");
|
||||
final String urlAndName = myURL + "#egg=" + myName;
|
||||
if (size == 0) {
|
||||
results.add(urlAndName);
|
||||
@@ -233,8 +246,9 @@ public class PyRequirement {
|
||||
return results;
|
||||
}
|
||||
else {
|
||||
return Collections.singletonList(toString());
|
||||
results.add(toString());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -372,8 +386,9 @@ public class PyRequirement {
|
||||
if (!editableEggMatcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
final String url = editableEggMatcher.group(1);
|
||||
final String egg = editableEggMatcher.group(2);
|
||||
final boolean editable = editableEggMatcher.group(1) != null;
|
||||
final String url = editableEggMatcher.group(2);
|
||||
final String egg = editableEggMatcher.group(3);
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -381,7 +396,7 @@ public class PyRequirement {
|
||||
if (nameVersionMatcher.matches()) {
|
||||
final String name = normalizeName(nameVersionMatcher.group(1));
|
||||
final String version = normalizeVersion(nameVersionMatcher.group(3));
|
||||
return new PyRequirement(name, version, url);
|
||||
return new PyRequirement(name, version, url, editable);
|
||||
}
|
||||
else {
|
||||
final Matcher nameMatcher = NAME.matcher(egg);
|
||||
@@ -389,7 +404,7 @@ public class PyRequirement {
|
||||
return null;
|
||||
}
|
||||
final String name = normalizeName(nameMatcher.group(1));
|
||||
return new PyRequirement(name, null, url);
|
||||
return new PyRequirement(name, null, url, editable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public interface PySliceExpression extends PyExpression {
|
||||
@NotNull
|
||||
PyExpression getOperand();
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -2,11 +2,11 @@ package com.jetbrains.python.psi.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PythonDialectsTokenSetProvider;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.psi.PySliceExpression;
|
||||
import com.jetbrains.python.psi.PySliceItem;
|
||||
import com.jetbrains.python.psi.types.PyTupleType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -20,15 +20,25 @@ public class PySliceExpressionImpl extends PyElementImpl implements PySliceExpre
|
||||
super(astNode);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getType(@NotNull TypeEvalContext context) {
|
||||
return context.getType(getOperand());
|
||||
final PyType type = context.getType(getOperand());
|
||||
// TODO: Currently we don't evaluate the static range of the slice, so we have to return a generic tuple type without elements
|
||||
if (type instanceof PyTupleType) {
|
||||
return PyBuiltinCache.getInstance(this).getTupleType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PyExpression getOperand() {
|
||||
return childToPsiNotNull(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PySliceItem getSliceItem() {
|
||||
return PsiTreeUtil.getChildOfType(this, PySliceItem.class);
|
||||
}
|
||||
|
||||
@@ -147,9 +147,12 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
PsiElement definition = instruction.getElement();
|
||||
NameDefiner definer = null;
|
||||
// TODO: This check may slow down resolving, but it is the current solution to the comprehension scopes problem
|
||||
final PyComprehensionElement defComprh = PsiTreeUtil.getParentOfType(definition, PyComprehensionElement.class);
|
||||
if (defComprh != null && defComprh != PsiTreeUtil.getParentOfType(element, PyComprehensionElement.class)) {
|
||||
continue;
|
||||
final PyComprehensionElement definitionComprehension = PsiTreeUtil.getParentOfType(definition, PyComprehensionElement.class);
|
||||
if (definitionComprehension != null) {
|
||||
final PyComprehensionElement elementComprehension = PsiTreeUtil.getParentOfType(element, PyComprehensionElement.class);
|
||||
if (elementComprehension == null || !PsiTreeUtil.isAncestor(definitionComprehension, elementComprehension, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (definition instanceof NameDefiner && !(definition instanceof PsiNamedElement)) {
|
||||
definer = (NameDefiner)definition;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.jetbrains.python.psi.types;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -8,5 +9,5 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public interface PyTypeReference extends PyType {
|
||||
@Nullable
|
||||
PyType resolve(PsiElement context, TypeEvalContext typeEvalContext);
|
||||
PyType resolve(@Nullable PsiElement context, @NotNull TypeEvalContext typeEvalContext);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ public abstract class PyTypeReferenceImpl implements PyTypeReference {
|
||||
return ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType resolve(@Nullable PsiElement context, TypeEvalContext typeEvalContext) {
|
||||
public PyType resolve(@Nullable PsiElement context, @NotNull TypeEvalContext typeEvalContext) {
|
||||
Set<PyTypeReferenceImpl> seen = new HashSet<PyTypeReferenceImpl>();
|
||||
seen.add(this);
|
||||
PyType resolved;
|
||||
|
||||
@@ -12,4 +12,10 @@ a, b = <warning descr="Too many values to unpack">c</warning>
|
||||
a, b = <warning descr="Too many values to unpack">[1, 2, 3]</warning>
|
||||
a, b = <warning descr="Too many values to unpack">'str'</warning>
|
||||
a, b = <warning descr="Too many values to unpack">{1, 2, 3}</warning>
|
||||
a, b = <warning descr="Too many values to unpack">{1:2, 2: 3, 3:4}</warning>
|
||||
a, b = <warning descr="Too many values to unpack">{1:2, 2: 3, 3:4}</warning>
|
||||
|
||||
# PY-6315
|
||||
def test_tuple_slice():
|
||||
def f():
|
||||
return 1, 2, 3
|
||||
x, y = f()[:2]
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
def f(xs, ys):
|
||||
return [[(x, y) for y in ys] for x in xs]
|
||||
@@ -0,0 +1,9 @@
|
||||
def bar():
|
||||
if 11 > 4:
|
||||
print('ok')
|
||||
|
||||
|
||||
def main(indices):
|
||||
foo = True
|
||||
bar()
|
||||
return foo
|
||||
@@ -0,0 +1,5 @@
|
||||
def main(indices):
|
||||
foo = True
|
||||
<selection>if 11 > 4:
|
||||
print('ok')</selection>
|
||||
return foo
|
||||
+5
@@ -97,6 +97,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-6316
|
||||
public void testNestedComprehensions() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doMultiFileTest() {
|
||||
myFixture.copyFileToProject("inspections/PyUnresolvedReferencesInspection/__init__.py", "PyUnresolvedReferencesInspection/__init__.py");
|
||||
myFixture.copyFileToProject("inspections/PyUnresolvedReferencesInspection/" + getTestName(true) + ".py",
|
||||
|
||||
@@ -162,4 +162,9 @@ public class PyExtractMethodTest extends LightMarkedTestCase {
|
||||
public void testLocalVarDefinedBeforeModifiedInside() {
|
||||
doTest("bar");
|
||||
}
|
||||
|
||||
// PY-6391
|
||||
public void testDefinedBeforeAccessedAfter() {
|
||||
doTest("bar");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user