Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2012-06-19 22:35:18 +04:00
4 changed files with 48 additions and 25 deletions
@@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
public class PythonReferenceImporter implements ReferenceImporter {
@Override
public boolean autoImportReferenceAtCursor(@NotNull final Editor editor, @NotNull final PsiFile file) {
if (!(file instanceof PyFile)) return false;
int caretOffset = editor.getCaretModel().getOffset();
@@ -68,7 +69,27 @@ public class PythonReferenceImporter implements ReferenceImporter {
return false;
}
private static TokenSet IS_IMPORT_STATEMENT = TokenSet.create(PyElementTypes.IMPORT_STATEMENT);
@Override
public boolean autoImportReferenceAt(@NotNull Editor editor, @NotNull PsiFile file, int offset) {
if (!(file instanceof PyFile)) return false;
PsiReference element = file.findReferenceAt(offset);
if (element instanceof PyReferenceExpression && isImportable((PsiElement)element)) {
final PyReferenceExpression refExpr = (PyReferenceExpression)element;
if (refExpr.getQualifier() == null) {
final PsiPolyVariantReference reference = refExpr.getReference();
if (reference.resolve() == null) {
AutoImportQuickFix fix = proposeImportFix(refExpr, reference);
if (fix != null && fix.getCandidatesCount() == 1) {
fix.invoke(file);
}
return true;
}
}
}
return false;
}
private static final TokenSet IS_IMPORT_STATEMENT = TokenSet.create(PyElementTypes.IMPORT_STATEMENT);
@Nullable
public static AutoImportQuickFix proposeImportFix(final PyElement node, PsiReference reference) {
@@ -87,7 +108,6 @@ public class PythonReferenceImporter implements ReferenceImporter {
return null;
}
PsiFile existing_import_file = null; // if there's a matching existing import, this it the file it imports
AutoImportQuickFix fix = new AutoImportQuickFix(node, reference, !PyCodeInsightSettings.getInstance().PREFER_FROM_IMPORT);
Set<String> seen_file_names = new HashSet<String>(); // true import names
// maybe the name is importable via some existing 'import foo' statement, and only needs a qualifier.
@@ -95,7 +115,8 @@ public class PythonReferenceImporter implements ReferenceImporter {
CollectProcessor import_prc = new CollectProcessor(IS_IMPORT_STATEMENT);
PyResolveUtil.treeCrawlUp(import_prc, node);
List<PsiElement> result = import_prc.getResult();
if (result.size() > 0) {
PsiFile existing_import_file = null; // if there's a matching existing import, this it the file it imports
if (!result.isEmpty()) {
for (PsiElement stmt : import_prc.getResult()) {
for (PyImportElement ielt : ((PyImportStatement)stmt).getImportElements()) {
final PyReferenceExpression src = ielt.getImportReferenceExpression();
@@ -130,7 +151,7 @@ public class PythonReferenceImporter implements ReferenceImporter {
if (isPossibleModuleReference(node)) {
symbols.addAll(findImportableModules(node.getContainingFile(), refText, project, scope));
}
if (symbols.size() > 0) {
if (!symbols.isEmpty()) {
for (PsiElement symbol : symbols) {
if (isIndexableTopLevel(symbol)) { // we only want top-level symbols
PsiFileSystemItem srcfile = symbol instanceof PsiFileSystemItem ? ((PsiFileSystemItem)symbol).getParent() : symbol.getContainingFile();
@@ -171,10 +192,7 @@ public class PythonReferenceImporter implements ReferenceImporter {
}
private static boolean isQualifier(PyElement node) {
if (node.getParent() instanceof PyReferenceExpression) {
return node == ((PyReferenceExpression) node.getParent()).getQualifier();
}
return false;
return node.getParent() instanceof PyReferenceExpression && node == ((PyReferenceExpression)node.getParent()).getQualifier();
}
private static boolean isPossibleModuleReference(PyElement node) {
@@ -227,7 +245,7 @@ public class PythonReferenceImporter implements ReferenceImporter {
return symbol instanceof PyTargetExpression;
}
private final static String[] AS_PREFIXES = {"other_", "one_more_", "different_", "pseudo_", "true_"};
private static final String[] AS_PREFIXES = {"other_", "one_more_", "different_", "pseudo_", "true_"};
// a no-frills recursive accumulating scan
private static void collectIdentifiers(PsiElement node, Collection<String> dst) {
@@ -13,7 +13,7 @@ import com.intellij.openapi.editor.actions.SplitLineAction;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
@@ -54,8 +54,8 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
EditorActionHandler originalHandler) {
int offset = caretOffset.get();
if (editor instanceof EditorWindow) {
file = InjectedLanguageUtil.getTopLevelFile(file);
editor = InjectedLanguageUtil.getTopLevelEditor(editor);
file = InjectedLanguageFacadeImpl.getTopLevelFile(file);
editor = InjectedLanguageFacadeImpl.getTopLevelEditor(editor);
offset = editor.getCaretModel().getOffset();
}
if (!(file instanceof PyFile)) {
@@ -102,8 +102,9 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
addImportElementDeclaration(importElement, localDeclarations, ambiguousDeclarations);
if (PyNames.INIT_DOT_PY.equals(getName())) {
final PyQualifiedName qName = importElement.getImportedQName();
String parentPackage = getContainingDirectory().getName();
if (qName != null && qName.getComponentCount() > 1) {
final PsiDirectory containingDirectory = getContainingDirectory();
if (qName != null && qName.getComponentCount() > 1 && containingDirectory != null) {
String parentPackage = containingDirectory.getName();
final List<String> components = qName.getComponents();
if (components.get(components.size() - 2).equals(parentPackage)) {
localDeclarations.put(components.get(components.size()-1), importElement);
@@ -188,14 +189,16 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
@Nullable
private PsiElement findNameInNameDefiners(String name) {
long oocbModCount = myModificationTracker.getOutOfCodeBlockModificationCount();
if (oocbModCount != myNameDefinerOOCBModCount) {
myNameDefinerNegativeCache.clear();
myNameDefinerOOCBModCount = oocbModCount;
}
else {
if (myNameDefinerNegativeCache.contains(name)) {
return null;
synchronized (myNameDefinerNegativeCache) {
long oocbModCount = myModificationTracker.getOutOfCodeBlockModificationCount();
if (oocbModCount != myNameDefinerOOCBModCount) {
myNameDefinerNegativeCache.clear();
myNameDefinerOOCBModCount = oocbModCount;
}
else {
if (myNameDefinerNegativeCache.contains(name)) {
return null;
}
}
}
for (PsiElement definer : myNameDefiners) {
@@ -204,13 +207,15 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
result = findNameInStarImport(name, (PyFromImportStatement)definer);
}
else {
result = ((NameDefiner) definer).getElementNamed(name);
result = ((NameDefiner)definer).getElementNamed(name);
}
if (result != null) {
return result;
}
}
myNameDefinerNegativeCache.add(name);
synchronized (myNameDefinerNegativeCache) {
myNameDefinerNegativeCache.add(name);
}
return null;
}
@@ -54,7 +54,7 @@ public class PyPushDownTest extends PyClassRefactoringTest {
myFixture.checkResultByFile(baseName + ".after.py");
} catch (Exception e) {
if (expectedError == null) throw e;
assertEquals(expectedError, e.getMessage());
assertTrue(e.getMessage(), e.getMessage().contains(expectedError));
}
}
}