diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties b/python/helpers/StdlibTypes2.properties
similarity index 100%
rename from python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties
rename to python/helpers/StdlibTypes2.properties
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes3.properties b/python/helpers/StdlibTypes3.properties
similarity index 100%
rename from python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes3.properties
rename to python/helpers/StdlibTypes3.properties
diff --git a/python/helpers/icons/PythonHelpersIcons.java b/python/helpers/icons/PythonHelpersIcons.java
new file mode 100644
index 000000000000..c80728d8bc73
--- /dev/null
+++ b/python/helpers/icons/PythonHelpersIcons.java
@@ -0,0 +1,14 @@
+package icons;
+
+import com.intellij.openapi.util.IconLoader;
+
+import javax.swing.*;
+
+/**
+ * NOTE THIS FILE IS AUTO-GENERATED by the build/scripts/icons.gant
+ * Don't repeat mistakes of others ;-)
+ */
+public class PythonHelpersIcons {
+ public static final Icon Keybd_closed = IconLoader.getIcon("/coverage/htmlfiles/keybd_closed.png"); // 35x12
+ public static final Icon Keybd_open = IconLoader.getIcon("/coverage/htmlfiles/keybd_open.png"); // 35x12
+}
diff --git a/python/openapi/src/com/jetbrains/python/psi/WeakFileReference.java b/python/openapi/src/com/jetbrains/python/psi/WeakFileReference.java
new file mode 100644
index 000000000000..985835e36731
--- /dev/null
+++ b/python/openapi/src/com/jetbrains/python/psi/WeakFileReference.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2012 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.psi;
+
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
+import com.jetbrains.python.psi.types.TypeEvalContext;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public class WeakFileReference extends FileReference implements PsiReferenceEx {
+ public WeakFileReference(FileReferenceSet fileReferenceSet, TextRange range, int index, String text) {
+ super(fileReferenceSet, range, index, text);
+ }
+
+ @Nullable
+ @Override
+ public HighlightSeverity getUnresolvedHighlightSeverity(TypeEvalContext context) {
+ return HighlightSeverity.WARNING;
+ }
+
+ @Nullable
+ @Override
+ public String getUnresolvedDescription() {
+ return null;
+ }
+}
diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java
index 3fb97fc94b8e..c924421a2f6c 100644
--- a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java
+++ b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java
@@ -15,7 +15,6 @@
*/
package com.jetbrains.python.templateLanguages;
-import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
@@ -26,10 +25,12 @@ import com.intellij.psi.ElementManipulators;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
-import com.intellij.psi.impl.source.resolve.reference.impl.providers.*;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceHelper;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceHelperRegistrar;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiFileSystemItemUtil;
import com.intellij.util.IncorrectOperationException;
-import com.jetbrains.python.psi.PsiReferenceEx;
-import com.jetbrains.python.psi.types.TypeEvalContext;
+import com.jetbrains.python.psi.WeakFileReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,7 @@ import java.util.Collection;
/**
* @author yole
*/
-public class TemplateFileReference extends FileReference implements PsiReferenceEx {
+public class TemplateFileReference extends WeakFileReference {
@NotNull private final FileReferenceSet myReferenceSet;
public TemplateFileReference(@NotNull FileReferenceSet fileReferenceSet, TextRange range, int index, String text) {
@@ -46,12 +47,6 @@ public class TemplateFileReference extends FileReference implements PsiReference
myReferenceSet = fileReferenceSet;
}
- @Nullable
- @Override
- public HighlightSeverity getUnresolvedHighlightSeverity(TypeEvalContext context) {
- return HighlightSeverity.WARNING;
- }
-
@Nullable
@Override
public String getUnresolvedDescription() {
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyQualifiedExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyQualifiedExpression.java
index 4c90d5077308..1a2ed465955e 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyQualifiedExpression.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyQualifiedExpression.java
@@ -1,6 +1,9 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiPolyVariantReference;
+import com.jetbrains.python.psi.resolve.PyResolveContext;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -27,4 +30,7 @@ public interface PyQualifiedExpression extends PyExpression {
*/
@Nullable
ASTNode getNameElement();
+
+ @NotNull
+ PsiPolyVariantReference getReference(PyResolveContext resolveContext);
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyReferenceExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyReferenceExpression.java
index 1dbfa329f11d..c2a6a3597836 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyReferenceExpression.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyReferenceExpression.java
@@ -30,7 +30,4 @@ public interface PyReferenceExpression extends PyQualifiedExpression, PyReferenc
@NotNull
PsiPolyVariantReference getReference();
-
- @NotNull
- PsiPolyVariantReference getReference(PyResolveContext resolveContext);
}
diff --git a/python/python-helpers.iml b/python/python-helpers.iml
index 880a7f9e4113..9d65a5f9a331 100644
--- a/python/python-helpers.iml
+++ b/python/python-helpers.iml
@@ -7,6 +7,7 @@
+
diff --git a/python/rest/src/icons/RestIcons.java b/python/rest/src/icons/RestIcons.java
new file mode 100644
index 000000000000..37a8509d1aee
--- /dev/null
+++ b/python/rest/src/icons/RestIcons.java
@@ -0,0 +1,13 @@
+package icons;
+
+import com.intellij.openapi.util.IconLoader;
+
+import javax.swing.*;
+
+/**
+ * NOTE THIS FILE IS AUTO-GENERATED by the build/scripts/icons.gant
+ * Don't repeat mistakes of others ;-)
+ */
+public class RestIcons {
+ public static final Icon Rst = IconLoader.getIcon("/com/jetbrains/rest/res/rst.png"); // 16x16
+}
diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index f4f140dcd059..3920ee02cd5c 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -455,6 +455,7 @@
+
diff --git a/python/src/com/jetbrains/python/buildout/BuildoutFacet.java b/python/src/com/jetbrains/python/buildout/BuildoutFacet.java
index de5a2ddab2bc..fecbb9ffa70e 100644
--- a/python/src/com/jetbrains/python/buildout/BuildoutFacet.java
+++ b/python/src/com/jetbrains/python/buildout/BuildoutFacet.java
@@ -97,6 +97,7 @@ public class BuildoutFacet extends Facet implements
/**
* Generates a sys.path[0:0] = [...] with paths that buildout script wants.
+ *
* @param module to get a buildout facet from
* @return the statement, or null if there's no buildout facet.
*/
@@ -158,7 +159,7 @@ public class BuildoutFacet extends Facet implements
}
return paths;
}
- catch(IOException e) {
+ catch (IOException e) {
LOG.info(e);
return null;
}
@@ -208,18 +209,20 @@ public class BuildoutFacet extends Facet implements
String text = VfsUtil.loadText(vFile);
String[] lines = LineTokenizer.tokenize(text, false);
int index = 0;
- while(index < lines.length && !lines [index].startsWith("def addsitepackages("))
+ while (index < lines.length && !lines[index].startsWith("def addsitepackages(")) {
index++;
- while(index < lines.length && !lines [index].trim().startsWith("buildout_paths = ["))
+ }
+ while (index < lines.length && !lines[index].trim().startsWith("buildout_paths = [")) {
index++;
+ }
index++;
- while(index < lines.length && !lines [index].trim().equals("]")) {
- String line = lines [index].trim();
+ while (index < lines.length && !lines[index].trim().equals("]")) {
+ String line = lines[index].trim();
if (line.endsWith(",")) {
- line = line.substring(0, line.length()-1);
+ line = line.substring(0, line.length() - 1);
}
if (line.startsWith("'") && line.endsWith("'")) {
- result.add(StringUtil.unescapeStringCharacters(line.substring(1, line.length()-1)));
+ result.add(StringUtil.unescapeStringCharacters(line.substring(1, line.length() - 1)));
}
index++;
}
@@ -243,10 +246,12 @@ public class BuildoutFacet extends Facet implements
// alter execution script
ParamsGroup script_params = params.getParamsGroup(PythonCommandLineState.GROUP_SCRIPT);
assert script_params != null;
- String normal_script = script_params.getParameters().get(0); // expect DjangoUtil.MANAGE_FILE
- String engulfer_path = PythonHelpersLocator.getHelperPath("pycharm/buildout_engulfer.py");
- new_env.put("PYCHARM_ENGULF_SCRIPT", getConfiguration().getScriptName());
- script_params.getParametersList().replaceOrPrepend(normal_script, engulfer_path);
+ if (script_params.getParameters().size() > 0) {
+ String normal_script = script_params.getParameters().get(0); // expect DjangoUtil.MANAGE_FILE
+ String engulfer_path = PythonHelpersLocator.getHelperPath("pycharm/buildout_engulfer.py");
+ new_env.put("PYCHARM_ENGULF_SCRIPT", getConfiguration().getScriptName());
+ script_params.getParametersList().replaceOrPrepend(normal_script, engulfer_path);
+ }
// add pycharm helpers to pythonpath so that fixGetpass is importable
PythonEnvUtil.addToPythonPath(new_env, PythonHelpersLocator.getHelpersRoot().getAbsolutePath());
@@ -280,7 +285,7 @@ public class BuildoutFacet extends Facet implements
String text = FileUtil.loadFile(cfg);
final PsiFile configFile = PsiFileFactory
.getInstance(getModule().getProject()).createFileFromText("buildout.cfg",
- BuildoutCfgLanguage.INSTANCE, text);
+ BuildoutCfgLanguage.INSTANCE, text);
if (configFile != null && configFile instanceof BuildoutCfgFile) {
return (BuildoutCfgFile)configFile;
}
@@ -290,7 +295,7 @@ public class BuildoutFacet extends Facet implements
}
return null;
}
-
+
public static List getScripts(@Nullable BuildoutFacet buildoutFacet, final VirtualFile baseDir) {
File rootPath = null;
if (buildoutFacet != null) {
diff --git a/python/src/com/jetbrains/python/buildout/config/BuildoutCfgProblemFileHighlightFilter.java b/python/src/com/jetbrains/python/buildout/config/BuildoutCfgProblemFileHighlightFilter.java
index 41b1afb7455b..ae20d7b4f65a 100644
--- a/python/src/com/jetbrains/python/buildout/config/BuildoutCfgProblemFileHighlightFilter.java
+++ b/python/src/com/jetbrains/python/buildout/config/BuildoutCfgProblemFileHighlightFilter.java
@@ -1,7 +1,6 @@
package com.jetbrains.python.buildout.config;
import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
diff --git a/python/src/com/jetbrains/python/codeInsight/PyTargetElementEvaluator.java b/python/src/com/jetbrains/python/codeInsight/PyTargetElementEvaluator.java
index 75056b874fce..3c24ee89fe3e 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyTargetElementEvaluator.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyTargetElementEvaluator.java
@@ -6,9 +6,11 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
+import com.jetbrains.python.psi.PyParameter;
+import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
+import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.resolve.PyResolveContext;
-import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,12 +31,15 @@ public class PyTargetElementEvaluator implements TargetElementEvaluator {
}
final PsiElement element = ref.getElement();
PsiElement result = ref.resolve();
- if (result instanceof PyReferenceExpression &&
- PsiTreeUtil.getParentOfType(element, ScopeOwner.class) == PsiTreeUtil.getParentOfType(result, ScopeOwner.class)) {
- QualifiedResolveResult resolveResult = ((PyReferenceExpression)result).followAssignmentsChain(PyResolveContext.noImplicits());
- PsiElement finalResult = resolveResult.getElement();
- if (PsiTreeUtil.getParentOfType(element, ScopeOwner.class) == PsiTreeUtil.getParentOfType(finalResult, ScopeOwner.class)) {
- return finalResult;
+ while (result instanceof PyReferenceExpression || result instanceof PyTargetExpression) {
+ PsiElement nextResult = ((PyQualifiedExpression) result).getReference(PyResolveContext.noImplicits()).resolve();
+ if (nextResult != null && nextResult != result &&
+ PsiTreeUtil.getParentOfType(element, ScopeOwner.class) == PsiTreeUtil.getParentOfType(result, ScopeOwner.class) &&
+ (nextResult instanceof PyReferenceExpression || nextResult instanceof PyTargetExpression || nextResult instanceof PyParameter)) {
+ result = nextResult;
+ }
+ else {
+ break;
}
}
return result;
diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java
index 7d750beaf938..ac303b484ffb 100644
--- a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java
+++ b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.lookup.TailTypeDecorator;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.patterns.ElementPattern;
+import com.intellij.patterns.PatternCondition;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.patterns.StandardPatterns;
import com.intellij.psi.*;
@@ -50,12 +51,12 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
final ASTNode ctxNode = context.getNode();
if (ctxNode != null && PyTokenTypes.STRING_NODES.contains(ctxNode.getElementType())) return false; // no sense inside string
PsiElement p = (PsiElement)element;
- int first_offset = p.getTextOffset();
+ int firstOffset = p.getTextRange().getStartOffset();
// we must be a stmt ourselves, not a part of another stmt
// try to climb to the stmt level with the same offset
while (true) {
if (p == null) return false;
- if (p.getTextOffset() != first_offset) return false;
+ if (p.getTextRange().getStartOffset() != firstOffset) return false;
if (p instanceof PyStatement) break;
p = p.getParent();
}
@@ -72,7 +73,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
PsiDocumentManager docMgr = PsiDocumentManager.getInstance(p.getProject());
Document doc = docMgr.getDocument(p.getContainingFile().getOriginalFile());
if (doc != null) {
- if (doc.getLineNumber(prev.getTextRange().getEndOffset()) == doc.getLineNumber(first_offset)) {
+ if (doc.getLineNumber(prev.getTextRange().getEndOffset()) == doc.getLineNumber(firstOffset)) {
return false; // same line
}
}
@@ -214,6 +215,9 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
private static final PsiElementPattern.Capture IN_STRING_LITERAL =
psiElement().inside(PyStringLiteralExpression.class);
+ private static final PsiElementPattern.Capture IN_FUNCTION_HEADER =
+ psiElement().inside(PyFunction.class).andNot(psiElement().inside(PyStatementList.class));
+
public static final PsiElementPattern.Capture AFTER_QUALIFIER =
psiElement().afterLeaf(psiElement().withText(".").inside(PyReferenceExpression.class));
@@ -229,12 +233,13 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
psiElement().withElementType(PyTokenTypes.DOT))
).inside(PyFromImportStatement.class);
- private static final PsiElementPattern.Capture IN_WITH_AFTER_REF =
- psiElement().afterLeaf(psiElement()
- .withElementType(PyTokenTypes.IDENTIFIER)
- .inside(PyReferenceExpression.class)
- .inside(PyWithStatement.class)
- );
+ public static final ElementPattern IN_WITH_AFTER_REF =
+ psiElement().afterLeaf(psiElement().inside(psiElement(PyWithItem.class).with(new PatternCondition("withoutAsKeyword") {
+ @Override
+ public boolean accepts(@NotNull PyWithItem item, ProcessingContext context) {
+ return item.getNode().findChildByType(PyTokenTypes.AS_KEYWORD) == null;
+ }
+ })));
private static final PsiElementPattern.Capture IN_EXCEPT_AFTER_REF =
psiElement().afterLeaf(psiElement()
@@ -509,6 +514,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andNot(IN_COMMENT)
.andNot(IN_IMPORT_STMT)
.andNot(IN_PARAM_LIST)
+ .andNot(IN_FUNCTION_HEADER)
.andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL)
,
new PyKeywordCompletionProvider("not", "lambda")
@@ -524,6 +530,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andNot(IN_IMPORT_STMT)
.and(NOT_PARAMETER_OR_DEFAULT_VALUE)
.andNot(AFTER_QUALIFIER)
+ .andNot(IN_FUNCTION_HEADER)
,
new PyKeywordCompletionProvider(TailType.NONE, "True", "False", "None")
);
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
index 1bcda3178fcf..4e03bd564f9e 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
@@ -5,6 +5,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyNames;
+import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.documentation.StructuredDocString;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
@@ -15,6 +16,7 @@ import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@@ -249,7 +251,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
final String name = level.isPy3K() ? "StdlibTypes3" : "StdlibTypes2";
if (result.isEmpty()) {
try {
- final InputStream s = getClass().getResourceAsStream(String.format("%s.properties", name));
+ final InputStream s = new FileInputStream(PythonHelpersLocator.getHelperFile(String.format("%s.properties", name)));
try {
result.load(s);
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
index 61e65cae5f51..e7dbfd93992b 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
@@ -221,7 +221,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
lock.wait(10);
}
catch (InterruptedException e) {
- LOG.error(e);
+ //pass
}
}
}
diff --git a/python/src/com/jetbrains/python/debugger/PyClassTreeChooserDialog.java b/python/src/com/jetbrains/python/debugger/PyClassTreeChooserDialog.java
index 3bdadd9d57c4..b681d334cfea 100644
--- a/python/src/com/jetbrains/python/debugger/PyClassTreeChooserDialog.java
+++ b/python/src/com/jetbrains/python/debugger/PyClassTreeChooserDialog.java
@@ -17,11 +17,9 @@ import java.util.List;
* @author traff
*/
public class PyClassTreeChooserDialog extends AbstractTreeClassChooserDialog{
- public PyClassTreeChooserDialog(String title,
- Project project,
- GlobalSearchScope scope,
- @Nullable Filter classFilter, @Nullable PyClass initialClass) {
- super(title, project, scope, classFilter, initialClass);
+ public PyClassTreeChooserDialog(String title, Project project, GlobalSearchScope scope, @Nullable Filter classFilter,
+ @Nullable PyClass initialClass) {
+ super(title, project, scope, PyClass.class, classFilter, initialClass);
}
@NotNull
diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
index 2210d8a59b32..46cdc7480740 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
@@ -38,10 +38,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.net.ServerSocket;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static javax.swing.SwingUtilities.invokeLater;
@@ -61,7 +58,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
private final Map> myRegisteredExceptionBreakpoints =
new ConcurrentHashMap>();
- private final List mySuspendedThreads = Lists.newArrayList();
+ private final List mySuspendedThreads = Collections.synchronizedList(Lists.newArrayList());
private final Map myStackFrameCache = Maps.newHashMap();
private final Map myNewVariableValue = Maps.newHashMap();
diff --git a/python/src/com/jetbrains/python/debugger/PyDebuggerEditorsProvider.java b/python/src/com/jetbrains/python/debugger/PyDebuggerEditorsProvider.java
index ba1fc8754f5d..e1b47b2285fa 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebuggerEditorsProvider.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebuggerEditorsProvider.java
@@ -46,15 +46,17 @@ public class PyDebuggerEditorsProvider extends XDebuggerEditorsProvider {
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
if (psiFile != null) {
int offset = sourcePosition.getOffset();
- final int lineEndOffset = document.getLineEndOffset(document.getLineNumber(offset));
- do {
- PsiElement element = psiFile.findElementAt(offset);
- if (element != null && !(element instanceof PsiWhiteSpace || element instanceof PsiComment)) {
- return PyPsiUtils.getStatement(element);
+ if (offset >= 0 && offset < document.getTextLength()) {
+ final int lineEndOffset = document.getLineEndOffset(document.getLineNumber(offset));
+ do {
+ PsiElement element = psiFile.findElementAt(offset);
+ if (element != null && !(element instanceof PsiWhiteSpace || element instanceof PsiComment)) {
+ return PyPsiUtils.getStatement(element);
+ }
+ offset = element.getTextRange().getEndOffset() + 1;
}
- offset = element.getTextRange().getEndOffset() + 1;
+ while (offset < lineEndOffset);
}
- while (offset < lineEndOffset);
}
}
return null;
diff --git a/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java b/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java
index 009811ab0b2d..ac51515a5e33 100644
--- a/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java
+++ b/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java
@@ -141,7 +141,7 @@ public class PySignatureCacheManagerImpl extends PySignatureCacheManager {
try {
data = CALL_SIGNATURES_ATTRIBUTE.readAttributeBytes(file);
}
- catch (IOException e) {
+ catch (Exception e) {
data = null;
}
diff --git a/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java b/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java
index 87bd5e09efe3..7210f6493bbc 100644
--- a/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java
+++ b/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java
@@ -8,6 +8,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.PyDocStringOwner;
+import com.jetbrains.python.psi.PyImportElement;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import com.jetbrains.python.psi.impl.PyStringLiteralExpressionImpl;
import com.jetbrains.python.psi.types.PyType;
@@ -85,7 +86,7 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
final PyTypeParser.ParseResult parseResult = PyTypeParser.parse(anchor, s.toString());
final Map types = parseResult.getTypes();
if (types.isEmpty()) {
- result.add(new DocStringTypeReference(anchor, s.getTextRange().shiftRight(offset), s.getTextRange().shiftRight(offset), null));
+ result.add(new DocStringTypeReference(anchor, s.getTextRange().shiftRight(offset), s.getTextRange().shiftRight(offset), null, null));
}
offset = s.getTextRange().getStartOffset() + offset;
final Map fullRanges = parseResult.getFullRanges();
@@ -93,7 +94,8 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
final PyType t = pair.getValue();
final TextRange range = pair.getKey().shiftRight(offset);
final TextRange fullRange = fullRanges.containsKey(t) ? fullRanges.get(t).shiftRight(offset) : range;
- result.add(new DocStringTypeReference(anchor, range, fullRange, t));
+ final PyImportElement importElement = parseResult.getImports().get(t);
+ result.add(new DocStringTypeReference(anchor, range, fullRange, t, importElement));
}
return result;
}
diff --git a/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java b/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java
index f783e274219b..c005ced7c2b8 100644
--- a/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java
+++ b/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java
@@ -6,29 +6,36 @@ import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
-import com.jetbrains.python.psi.impl.PyImportedModule;
import com.jetbrains.python.psi.impl.PyQualifiedName;
+import com.jetbrains.python.psi.impl.ResolveResultList;
+import com.jetbrains.python.psi.resolve.ImportedResolveResult;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
+import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
* User : catherine
*/
-public class DocStringTypeReference extends PsiReferenceBase {
- private PyType myType;
- private TextRange myFullRange;
+public class DocStringTypeReference extends PsiPolyVariantReferenceBase {
+ @Nullable private PyType myType;
+ @NotNull private TextRange myFullRange;
+ @Nullable private final PyImportElement myImportElement;
- public DocStringTypeReference(PsiElement element, TextRange range, TextRange fullRange, @Nullable PyType type) {
+ public DocStringTypeReference(PsiElement element, TextRange range, @NotNull TextRange fullRange, @Nullable PyType type,
+ @Nullable PyImportElement importElement) {
super(element, range);
myFullRange = fullRange;
myType = type;
+ myImportElement = importElement;
}
+ @Nullable
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
if (element.equals(resolve())) {
@@ -49,7 +56,7 @@ public class DocStringTypeReference extends PsiReferenceBase {
}
public boolean isSoft() {
- return true;
+ return false;
}
@Override
@@ -68,16 +75,28 @@ public class DocStringTypeReference extends PsiReferenceBase {
return super.isReferenceTo(element);
}
- @Nullable
- public PsiElement resolve() {
+ @NotNull
+ @Override
+ public ResolveResult[] multiResolve(boolean incompleteCode) {
+ PsiElement result = null;
+ final ResolveResultList results = new ResolveResultList();
if (myType instanceof PyClassType) {
- return ((PyClassType)myType).getPyClass();
+ result = ((PyClassType)myType).getPyClass();
}
- if (myType instanceof PyImportedModuleType) {
- final PyImportedModule module = ((PyImportedModuleType)myType).getImportedModule();
- return module.resolve();
+ else if (myType instanceof PyImportedModuleType) {
+ result = ((PyImportedModuleType)myType).getImportedModule().resolve();
}
- return null;
+ if (result != null) {
+ if (myImportElement != null) {
+ results.add(new ImportedResolveResult(result,
+ RatedResolveResult.RATE_NORMAL,
+ Collections.singletonList(myImportElement)));
+ }
+ else {
+ results.poke(result, RatedResolveResult.RATE_NORMAL);
+ }
+ }
+ return results.toArray(new ResolveResult[0]);
}
@NotNull
diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
index 25623b87c981..12b81ea4f41d 100644
--- a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
+++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
@@ -36,6 +36,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
@@ -385,16 +386,22 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
}
private static boolean pageExists(String url) {
+ if (new File(url).exists()) {
+ return true;
+ }
HttpClient client = new HttpClient();
client.setTimeout(5 * 1000);
client.setConnectionTimeout(5 * 1000);
- HeadMethod method = new HeadMethod(url);
try {
+ HeadMethod method = new HeadMethod(url);
int rc = client.executeMethod(method);
if (rc == 404) {
return false;
}
}
+ catch (IllegalArgumentException e) {
+ return false;
+ }
catch (IOException ignored) {
}
return true;
diff --git a/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java b/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
index 934cdab8df82..622c87e3bdb5 100644
--- a/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
+++ b/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
@@ -4,12 +4,16 @@ import com.intellij.find.findUsages.FindUsagesHandler;
import com.intellij.find.findUsages.FindUsagesHandlerFactory;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFileSystemItem;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyFunction;
+import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.psi.impl.PyImportedModule;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
@@ -22,14 +26,22 @@ public class PyFindUsagesHandlerFactory extends FindUsagesHandlerFactory {
@Override
public boolean canFindUsages(@NotNull PsiElement element) {
return element instanceof PyClass ||
- (element instanceof PyFile && PyNames.INIT_DOT_PY.equals(((PyFile) element).getName())) ||
+ (element instanceof PyFile && PyUtil.isPackage((PyFile)element)) ||
+ element instanceof PyImportedModule ||
element instanceof PyFunction;
}
+ @Nullable
@Override
public FindUsagesHandler createFindUsagesHandler(@NotNull PsiElement element, boolean forHighlightUsages) {
- if (element instanceof PyFile) {
- return new PyModuleFindUsagesHandler((PyFile) element);
+ if (element instanceof PyImportedModule) {
+ final PsiElement resolved = ((PyImportedModule)element).resolve();
+ if (resolved != null) {
+ element = resolved;
+ }
+ }
+ if (element instanceof PsiFileSystemItem) {
+ return new PyModuleFindUsagesHandler((PsiFileSystemItem)element);
}
if (element instanceof PyFunction) {
if (!forHighlightUsages) {
@@ -60,7 +72,10 @@ public class PyFindUsagesHandlerFactory extends FindUsagesHandlerFactory {
}
return new PyFunctionFindUsagesHandler(element);
}
- return new PyClassFindUsagesHandler((PyClass)element);
+ if (element instanceof PyClass) {
+ return new PyClassFindUsagesHandler((PyClass)element);
+ }
+ return null;
}
private static boolean isInClassobj(PyFunction fun) {
diff --git a/python/src/com/jetbrains/python/findUsages/PyModuleFindUsagesHandler.java b/python/src/com/jetbrains/python/findUsages/PyModuleFindUsagesHandler.java
index 61955046dc30..9441948095bb 100644
--- a/python/src/com/jetbrains/python/findUsages/PyModuleFindUsagesHandler.java
+++ b/python/src/com/jetbrains/python/findUsages/PyModuleFindUsagesHandler.java
@@ -8,7 +8,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
-import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyUtil;
import org.jetbrains.annotations.NotNull;
@@ -18,7 +17,7 @@ import org.jetbrains.annotations.NotNull;
public class PyModuleFindUsagesHandler extends FindUsagesHandler {
private final PsiFileSystemItem myElement;
- protected PyModuleFindUsagesHandler(@NotNull PyFile file) {
+ protected PyModuleFindUsagesHandler(@NotNull PsiFileSystemItem file) {
super(file);
final PsiElement e = PyUtil.turnInitIntoDir(file);
myElement = e instanceof PsiFileSystemItem ? (PsiFileSystemItem)e : file;
diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
index 219e21aa3459..03dab57430dc 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
@@ -39,6 +39,7 @@ import com.jetbrains.python.codeInsight.imports.OptimizeImportsQuickFix;
import com.jetbrains.python.codeInsight.imports.PythonReferenceImporter;
import com.jetbrains.python.console.PydevConsoleRunner;
import com.jetbrains.python.documentation.DocStringParameterReference;
+import com.jetbrains.python.documentation.DocStringTypeReference;
import com.jetbrains.python.packaging.PyPIPackageUtil;
import com.jetbrains.python.packaging.PyPackageManager;
import com.jetbrains.python.packaging.PyRequirement;
@@ -366,6 +367,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
private void registerUnresolvedReferenceProblem(@NotNull PyElement node, @NotNull PsiReference reference,
@NotNull HighlightSeverity severity) {
+ if (reference instanceof DocStringTypeReference) {
+ return;
+ }
String description = null;
final String text = reference.getElement().getText();
TextRange rangeInElement = reference.getRangeInElement();
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 7cd8ea4f44bc..d9875cf384ad 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -361,23 +361,6 @@ public class PyUtil {
return superClasses;
}
- /**
- * Finds the first identifier AST node under target element, and returns its text.
- *
- * @param target
- * @return identifier text, or null.
- */
- public static
- @Nullable
- String getIdentifier(PsiElement target) {
- ASTNode node = target.getNode();
- if (node != null) {
- ASTNode ident_node = node.findChildByType(PyTokenTypes.IDENTIFIER);
- if (ident_node != null) return ident_node.getText();
- }
- return null;
- }
-
// TODO: move to a more proper place?
@@ -392,16 +375,16 @@ public class PyUtil {
if (ref != null) {
PyExpression qualifier = ref.getQualifier();
if (qualifier != null) {
- String attr_name = getIdentifier(ref);
- if ("__class__".equals(attr_name)) {
- PyType qual_type = context.getType(qualifier);
- if (qual_type instanceof PyClassType) {
- return new PyClassTypeImpl(((PyClassType)qual_type).getPyClass(), true); // always as class, never instance
+ String attr_name = ref.getReferencedName();
+ if (PyNames.CLASS.equals(attr_name)) {
+ PyType qualifierType = context.getType(qualifier);
+ if (qualifierType instanceof PyClassType) {
+ return new PyClassTypeImpl(((PyClassType)qualifierType).getPyClass(), true); // always as class, never instance
}
}
- else if ("__dict__".equals(attr_name)) {
- PyType qual_type = context.getType(qualifier);
- if (qual_type instanceof PyClassType && ((PyClassType)qual_type).isDefinition()) {
+ else if (PyNames.DICT.equals(attr_name)) {
+ PyType qualifierType = context.getType(qualifier);
+ if (qualifierType instanceof PyClassType && ((PyClassType)qualifierType).isDefinition()) {
return PyBuiltinCache.getInstance(ref).getDictType();
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java
index a82c317016ac..4a387ce3392b 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java
@@ -4,7 +4,6 @@ import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.stubs.IStubElementType;
@@ -202,11 +201,7 @@ public class PyImportElementImpl extends PyBaseElementImpl
}
if (qName.getComponentCount() == 1) {
if (resolveImportElement) {
- final PsiElement element = ResolveImportUtil.resolveImportElement(this, PyQualifiedName.fromComponents(name));
- if (element instanceof PsiDirectory) {
- return createImportedModule(name);
- }
- return element;
+ return ResolveImportUtil.resolveImportElement(this, PyQualifiedName.fromComponents(name));
}
return this;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java b/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java
index 1716ce244be2..38b8ade0769b 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyImportedModule.java
@@ -134,7 +134,9 @@ public class PyImportedModule extends LightElement implements NameDefiner {
@Nullable
private static PsiElement resolve(PyImportElement importElement, @NotNull final PyQualifiedName prefix) {
- return PyUtil.turnDirIntoInit(ResolveImportUtil.resolveImportElement(importElement, prefix));
+ final PsiElement resolved = ResolveImportUtil.resolveImportElement(importElement, prefix);
+ final PsiElement packageInit = PyUtil.turnDirIntoInit(resolved);
+ return packageInit != null ? packageInit : resolved;
}
public boolean isAncestorOf(PyImportedModule other) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
index eafcb179fd1f..0a227454c8c1 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
@@ -5,6 +5,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
import com.intellij.psi.ResolveResult;
import com.intellij.psi.search.GlobalSearchScope;
@@ -481,10 +482,15 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl types = new HashMap();
final Map fullRanges = new HashMap();
- final PyType t = parse(anchor, type, types, fullRanges, 0);
- return new ParseResult(t, types, fullRanges);
+ final Map imports = new HashMap();
+ final PyType t = parse(anchor, type, types, fullRanges, imports, 0);
+ return new ParseResult(t, types, fullRanges, imports);
}
public static class ParseResult {
@Nullable private PyType myType;
@NotNull private Map myTypes;
@NotNull private Map myFullRanges;
+ @NotNull private final Map myImports;
- ParseResult(@Nullable PyType type, @NotNull Map types, @NotNull Map fullRanges) {
+ ParseResult(@Nullable PyType type, @NotNull Map types, @NotNull Map fullRanges,
+ @NotNull Map imports) {
myType = type;
myTypes = types;
myFullRanges = fullRanges;
+ myImports = imports;
}
@Nullable
@@ -69,11 +73,16 @@ public class PyTypeParser {
public Map getFullRanges() {
return myFullRanges;
}
+
+ @NotNull
+ public Map getImports() {
+ return myImports;
+ }
}
@Nullable
private static PyType parse(@Nullable PsiElement anchor, @NotNull String type, @NotNull Map types,
- @NotNull Map fullRanges, int offset) {
+ @NotNull Map fullRanges, @NotNull Map imports, int offset) {
if (anchor == null || !anchor.isValid()) {
return null;
}
@@ -87,10 +96,10 @@ public class PyTypeParser {
return t;
}
if (type.startsWith("(") && type.endsWith(")")) {
- return parseTupleType(anchor, type.substring(1, type.length() - 1), types, fullRanges, offset + 1);
+ return parseTupleType(anchor, type.substring(1, type.length() - 1), types, fullRanges, imports, offset + 1);
}
if (type.contains(" or ")) {
- return parseUnionType(anchor, type, types, fullRanges, offset);
+ return parseUnionType(anchor, type, types, fullRanges, imports, offset);
}
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(anchor);
if (type.equals("unknown")) {
@@ -132,7 +141,7 @@ public class PyTypeParser {
return t;
}
if (type.startsWith("dict from")) {
- return parseDictFromToType(anchor, type, types, fullRanges, offset);
+ return parseDictFromToType(anchor, type, types, fullRanges, imports, offset);
}
if (type.equals("integer") || (type.equals("long") && LanguageLevel.forElement(anchor).isPy3K())) {
final PyType t = builtinCache.getIntType();
@@ -144,8 +153,8 @@ public class PyTypeParser {
}
final Matcher m = PARAMETRIZED_CLASS.matcher(type);
if (m.matches()) {
- final PyType objType = parseObjectType(anchor, m.group(1), builtinCache, types, fullRanges, offset + m.start(1));
- final PyType elementType = parse(anchor, m.group(2), types, fullRanges, offset + m.start(2));
+ final PyType objType = parseObjectType(anchor, m.group(1), builtinCache, types, fullRanges, imports, offset + m.start(1));
+ final PyType elementType = parse(anchor, m.group(2), types, fullRanges, imports, offset + m.start(2));
if (objType != null) {
if (objType instanceof PyClassType && elementType != null) {
return new PyCollectionTypeImpl(((PyClassType)objType).getPyClass(), false, elementType);
@@ -153,12 +162,13 @@ public class PyTypeParser {
return objType;
}
}
- return parseObjectType(anchor, type, builtinCache, types, fullRanges, offset);
+ return parseObjectType(anchor, type, builtinCache, types, fullRanges, imports, offset);
}
@Nullable
private static PyType parseObjectType(@NotNull PsiElement anchor, @NotNull String type, @NotNull PyBuiltinCache builtinCache,
- @NotNull Map types, @NotNull Map fullRanges, int offset) {
+ @NotNull Map types, @NotNull Map fullRanges,
+ @NotNull Map imports, int offset) {
final TextRange whole = new TextRange(offset, offset + type.length());
final PyClassType classType = builtinCache.getObjectType(type);
if (classType != null) {
@@ -170,6 +180,7 @@ public class PyTypeParser {
final PyClass aClass = ((PyFile)anchorFile).findTopLevelClass(type);
if (aClass != null) {
final PyType t = new PyClassTypeImpl(aClass, false);
+ t.assertValid("PyFile.findTopLevelClass()");
types.put(whole, t);
return t;
}
@@ -187,6 +198,7 @@ public class PyTypeParser {
final PyType pyType = getTypeFromQName(anchor, qName, whole, unusedRanges, fullRanges, offset);
if (pyType != null) {
types.put(whole, pyType);
+ imports.put(pyType, element);
return pyType;
}
}
@@ -199,6 +211,7 @@ public class PyTypeParser {
final Collection classes = PyClassNameIndex.find(type, anchor.getProject(), true);
if (classes.size() == 1) {
final PyType t = new PyClassTypeImpl(classes.iterator().next(), false);
+ t.assertValid("PyClassNameIndex.find().iterator().next()");
types.put(whole, t);
return t;
}
@@ -237,9 +250,12 @@ public class PyTypeParser {
if (t instanceof PyClassType) {
t = ((PyClassType)t).toInstance();
}
- types.put(classRange.shiftRight(offset), t);
- fullRanges.put(t, whole);
- return t;
+ if (t != null) {
+ t.assertValid("PyImportedModuleType.resolveMember()");
+ types.put(classRange.shiftRight(offset), t);
+ fullRanges.put(t, whole);
+ return t;
+ }
}
}
}
@@ -247,6 +263,7 @@ public class PyTypeParser {
for (PyClass aClass : classes) {
if (qName.equals(aClass.getQualifiedName())) {
final PyType t = new PyClassTypeImpl(aClass, false);
+ t.assertValid("PyClassNameIndex.find()");
types.put(classRange.shiftRight(offset), t);
fullRanges.put(t, whole);
return t;
@@ -257,6 +274,7 @@ public class PyTypeParser {
final String name = aClass.getQualifiedName();
if (name != null && name.startsWith("_")) {
final PyType t = new PyClassTypeImpl(aClass, false);
+ t.assertValid("PyClassNameIndex.find() for _foo");
types.put(classRange.shiftRight(offset), t);
fullRanges.put(t, whole);
return t;
@@ -268,24 +286,26 @@ public class PyTypeParser {
@Nullable
private static PyType parseTupleType(@NotNull PsiElement anchor, @NotNull String elementTypeNames, @NotNull Map types,
- @NotNull Map fullRanges, int offset) {
+ @NotNull Map fullRanges, @NotNull Map imports,
+ int offset) {
final List ranges = splitRanges(elementTypeNames, ",");
final List elementTypes = new ArrayList();
for (TextRange range : ranges) {
- elementTypes.add(parse(anchor, range.substring(elementTypeNames), types, fullRanges, offset + range.getStartOffset()));
+ elementTypes.add(parse(anchor, range.substring(elementTypeNames), types, fullRanges, imports, offset + range.getStartOffset()));
}
return PyTupleType.create(anchor, elementTypes.toArray(new PyType[elementTypes.size()]));
}
@Nullable
private static PyType parseDictFromToType(@NotNull PsiElement anchor, @NotNull String type, @NotNull Map types,
- @NotNull Map fullRanges, int offset) {
+ @NotNull Map fullRanges, @NotNull Map imports,
+ int offset) {
final Matcher m = DICT_TYPE.matcher(type);
PyClassType dict = PyBuiltinCache.getInstance(anchor).getDictType();
if (dict != null) {
if (m.matches()) {
- PyType from = parse(anchor, m.group(1), types, fullRanges, offset + m.start(1));
- PyType to = parse(anchor, m.group(2), types, fullRanges, offset + m.start(2));
+ PyType from = parse(anchor, m.group(1), types, fullRanges, imports, offset + m.start(1));
+ PyType to = parse(anchor, m.group(2), types, fullRanges, imports, offset + m.start(2));
final PyType p = PyTupleType.create(anchor, new PyType[] {from, to});
return new PyCollectionTypeImpl(dict.getPyClass(), false, p);
}
@@ -296,11 +316,12 @@ public class PyTypeParser {
@Nullable
private static PyType parseUnionType(@NotNull PsiElement anchor, @NotNull String type, @NotNull Map types,
- @NotNull Map fullRanges, int offset) {
+ @NotNull Map fullRanges, @NotNull Map imports,
+ int offset) {
final List ranges = splitRanges(type, " or ");
PyType result = null;
for (TextRange range : ranges) {
- final PyType t = parse(anchor, range.substring(type), types, fullRanges, offset + range.getStartOffset());
+ final PyType t = parse(anchor, range.substring(type), types, fullRanges, imports, offset + range.getStartOffset());
result = (result == null) ? t : PyUnionType.union(result, t);
}
return result;
diff --git a/python/src/com/jetbrains/python/sdk/PySkeletonGenerator.java b/python/src/com/jetbrains/python/sdk/PySkeletonGenerator.java
index 64b22c1785ae..ccbf403fdc40 100644
--- a/python/src/com/jetbrains/python/sdk/PySkeletonGenerator.java
+++ b/python/src/com/jetbrains/python/sdk/PySkeletonGenerator.java
@@ -199,7 +199,7 @@ public class PySkeletonGenerator {
return new ListBinariesResult(generatorVersion, binaries);
}
- public boolean deleteOrLog(File item) {
+ public boolean deleteOrLog(@NotNull File item) {
boolean deleted = item.delete();
if (!deleted) LOG.warn("Failed to delete skeleton file " + item.getAbsolutePath());
return deleted;
diff --git a/python/testData/completion/dunderClass.after.py b/python/testData/completion/dunderClass.after.py
new file mode 100644
index 000000000000..aaaffce5f04b
--- /dev/null
+++ b/python/testData/completion/dunderClass.after.py
@@ -0,0 +1,4 @@
+class Foo(object):
+ xyzzy = 3
+ def fun(self):
+ a = self.__class__.xyzzy
\ No newline at end of file
diff --git a/python/testData/completion/dunderClass.py b/python/testData/completion/dunderClass.py
new file mode 100644
index 000000000000..4d1a9136ac59
--- /dev/null
+++ b/python/testData/completion/dunderClass.py
@@ -0,0 +1,4 @@
+class Foo(object):
+ xyzzy = 3
+ def fun(self):
+ a = self.__class__.x
\ No newline at end of file
diff --git a/python/testData/findUsages/NamespacePackageUsages/a.py b/python/testData/findUsages/NamespacePackageUsages/a.py
new file mode 100644
index 000000000000..79cdd72a726c
--- /dev/null
+++ b/python/testData/findUsages/NamespacePackageUsages/a.py
@@ -0,0 +1,3 @@
+import nspkg1.m1
+
+print(nspkg1)
\ No newline at end of file
diff --git a/python/testData/findUsages/NamespacePackageUsages/b.py b/python/testData/findUsages/NamespacePackageUsages/b.py
new file mode 100644
index 000000000000..9b2491c9488f
--- /dev/null
+++ b/python/testData/findUsages/NamespacePackageUsages/b.py
@@ -0,0 +1 @@
+import nspkg1
\ No newline at end of file
diff --git a/python/testData/findUsages/NamespacePackageUsages/nspkg1/m1.py b/python/testData/findUsages/NamespacePackageUsages/nspkg1/m1.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/importUsedInDocString.py b/python/testData/inspections/PyUnresolvedReferencesInspection/importUsedInDocString.py
new file mode 100644
index 000000000000..af34c174f899
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/importUsedInDocString.py
@@ -0,0 +1,7 @@
+from datetime import timedelta #pass
+
+def f(d):
+ """
+ :type d: timedelta or int
+ """
+ pass
diff --git a/python/testData/refactoring/rename/renameReassignedParameter.py b/python/testData/refactoring/rename/renameReassignedParameter.py
new file mode 100644
index 000000000000..0bcbbb4fb5ef
--- /dev/null
+++ b/python/testData/refactoring/rename/renameReassignedParameter.py
@@ -0,0 +1,6 @@
+def cover(a, lab=1):
+ item = a + lab
+ lab = 1
+ if a > 1:
+ lab = cover(item, lab)
+ return lab
\ No newline at end of file
diff --git a/python/testData/refactoring/rename/renameReassignedParameter_after.py b/python/testData/refactoring/rename/renameReassignedParameter_after.py
new file mode 100644
index 000000000000..cb790d291974
--- /dev/null
+++ b/python/testData/refactoring/rename/renameReassignedParameter_after.py
@@ -0,0 +1,6 @@
+def cover(a, bar=1):
+ item = a + bar
+ bar = 1
+ if a > 1:
+ bar = cover(item, bar)
+ return bar
\ No newline at end of file
diff --git a/python/testData/refactoring/rename/renameShadowingVariable.py b/python/testData/refactoring/rename/renameShadowingVariable.py
new file mode 100644
index 000000000000..bc7946d9ec3c
--- /dev/null
+++ b/python/testData/refactoring/rename/renameShadowingVariable.py
@@ -0,0 +1,3 @@
+def lab(): pass
+lab = 1
+print(lab)
diff --git a/python/testData/refactoring/rename/renameShadowingVariable_after.py b/python/testData/refactoring/rename/renameShadowingVariable_after.py
new file mode 100644
index 000000000000..1f26476ab745
--- /dev/null
+++ b/python/testData/refactoring/rename/renameShadowingVariable_after.py
@@ -0,0 +1,3 @@
+def lab(): pass
+bar = 1
+print(bar)
diff --git a/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java b/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java
index 3dad95b96527..956b7867b150 100644
--- a/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java
+++ b/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java
@@ -1,7 +1,11 @@
package com.jetbrains.python;
+import com.intellij.codeInsight.TargetElementUtilBase;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
import com.intellij.usageView.UsageInfo;
import com.jetbrains.python.fixtures.PyTestCase;
+import com.jetbrains.python.psi.LanguageLevel;
import java.util.*;
@@ -111,4 +115,26 @@ public class PyFindUsagesTest extends PyTestCase {
"testMethod = staticmethod(testMethod)",
"testMethod = staticmethod(testMethod)");
}
+
+ // PY-7348
+ public void testNamespacePackageUsages() {
+ setLanguageLevel(LanguageLevel.PYTHON33);
+ try {
+ final Collection usages = findMultiFileUsages("a.py");
+ assertEquals(3, usages.size());
+ } finally {
+ setLanguageLevel(null);
+ }
+ }
+
+ private Collection findMultiFileUsages(String filename) {
+ final String testName = getTestName(false);
+ myFixture.copyDirectoryToProject("findUsages/" + testName, "");
+ PsiDocumentManager.getInstance(myFixture.getProject()).commitAllDocuments();
+ myFixture.configureFromTempProjectFile(filename);
+ final int flags = TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED;
+ final PsiElement element = TargetElementUtilBase.findTargetElement(myFixture.getEditor(), flags);
+ assertNotNull(element);
+ return myFixture.findUsages(element);
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java
index 68440e23bb0e..d55cf9c6a58b 100644
--- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java
+++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java
@@ -9,7 +9,6 @@ import com.jetbrains.cython.psi.CythonFunction;
import com.jetbrains.cython.psi.CythonVariable;
import com.jetbrains.python.fixtures.PyResolveTestCase;
import com.jetbrains.python.psi.*;
-import com.jetbrains.python.psi.impl.PyImportedModule;
/**
* @author yole
@@ -364,10 +363,7 @@ public class PyMultiFileResolveTest extends PyResolveTestCase {
// PY-2813
public void testNamespacePackage() {
- final PsiElement element = doResolve();
- assertInstanceOf(element, PyImportedModule.class);
- final PyImportedModule module = (PyImportedModule)element;
- assertEquals("p1", module.getImportedPrefix().toString());
+ assertResolvesTo(PsiDirectory.class, "p1");
}
// PY-2813
@@ -408,10 +404,7 @@ public class PyMultiFileResolveTest extends PyResolveTestCase {
public void testPython33NamespacePackage() {
setLanguageLevel(LanguageLevel.PYTHON33);
try {
- final PsiElement element = doResolve();
- assertInstanceOf(element, PyImportedModule.class);
- final PyImportedModule module = (PyImportedModule)element;
- assertEquals("p1", module.getImportedPrefix().toString());
+ assertResolvesTo(PsiDirectory.class, "p1");
} finally {
setLanguageLevel(null);
}
diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
index c2c0c3442a11..d19648feefbf 100644
--- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
@@ -591,9 +591,13 @@ public class PythonCompletionTest extends PyTestCase {
doTest();
}
+ public void testDunderClass() { // PY-7327
+ doTest();
+ }
+
public void testAsInWith() { // PY-3701
setLanguageLevel(LanguageLevel.PYTHON27);
- assertTrue(doTestByText("with foo ").contains("as"));
+ assertTrue(doTestByText("with open(foo) ").contains("as"));
}
public void testAsInExcept() { // PY-1846
diff --git a/python/testSrc/com/jetbrains/python/codeInsight/PyCompletionPatternsTest.java b/python/testSrc/com/jetbrains/python/codeInsight/PyCompletionPatternsTest.java
index 1e8b95982010..539f6451c727 100644
--- a/python/testSrc/com/jetbrains/python/codeInsight/PyCompletionPatternsTest.java
+++ b/python/testSrc/com/jetbrains/python/codeInsight/PyCompletionPatternsTest.java
@@ -1,25 +1,33 @@
package com.jetbrains.python.codeInsight;
+import com.intellij.patterns.ElementPattern;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.codeInsight.completion.PyKeywordCompletionContributor;
import com.jetbrains.python.fixtures.PyTestCase;
+import com.jetbrains.python.psi.LanguageLevel;
/**
* @author yole
*/
public class PyCompletionPatternsTest extends PyTestCase {
public void testInFromImportAfterRef() {
- String text = "from . im";
- myFixture.configureByText(PythonFileType.INSTANCE, text);
- PsiElement element = myFixture.getFile().findElementAt(text.length() - 1);
- assertTrue(PyKeywordCompletionContributor.IN_FROM_IMPORT_AFTER_REF.accepts(element));
+ assertTrue(doTest("from . im", PyKeywordCompletionContributor.IN_FROM_IMPORT_AFTER_REF));
}
public void testAfterQualifier() {
- String text = "from . im";
+ assertFalse(doTest("from . im", PyKeywordCompletionContributor.AFTER_QUALIFIER));
+ }
+
+ public void testWith() {
+ setLanguageLevel(LanguageLevel.PYTHON27);
+ assertTrue(doTest("with open(foo) ", PyKeywordCompletionContributor.IN_WITH_AFTER_REF));
+ assertFalse(doTest("with open(foo) as ", PyKeywordCompletionContributor.IN_WITH_AFTER_REF));
+ }
+
+ private boolean doTest(final String text, final ElementPattern ref) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
PsiElement element = myFixture.getFile().findElementAt(text.length() - 1);
- assertFalse(PyKeywordCompletionContributor.AFTER_QUALIFIER.accepts(element));
+ return ref.accepts(element);
}
}
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
index 49d530b3777f..a5bbed89e7b9 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
@@ -185,6 +185,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
+ // PY-7315
+ public void testImportUsedInDocString() {
+ doTest();
+ }
+
private void doTest() {
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java
index 58cf712cfcec..ca5e06eb7be7 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java
@@ -91,6 +91,14 @@ public class PyRenameTest extends PyTestCase {
doTest("bar");
}
+ public void testRenameReassignedParameter() { // PY-3698
+ doTest("bar");
+ }
+
+ public void testRenameShadowingVariable() { // PY-7342
+ doTest("bar");
+ }
+
public void testRenameProperty() { // PY-5948
setLanguageLevel(LanguageLevel.PYTHON26);
try {