mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user