Merge branch 'python-fixes'

Conflicts:
	python/src/com/jetbrains/python/inspections/quickfix/AddFunctionQuickFix.java
This commit is contained in:
Andrey Vlasovskikh
2014-03-12 13:46:21 +04:00
16 changed files with 85 additions and 92 deletions
@@ -15,10 +15,7 @@
*/
package com.jetbrains.python.psi;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
@@ -131,34 +128,6 @@ public enum LanguageLevel {
public static final Key<LanguageLevel> KEY = new Key<LanguageLevel>("python.language.level");
@NotNull
public static LanguageLevel forFile(@NotNull VirtualFile virtualFile) {
if (virtualFile instanceof VirtualFileWindow)
virtualFile = ((VirtualFileWindow)virtualFile).getDelegate();
// Most of the cases should be handled by this one, PyLanguageLevelPusher pushes folders only
final VirtualFile folder = virtualFile.getParent();
if (folder != null) {
final LanguageLevel level = folder.getUserData(KEY);
if (level != null) return level;
}
else {
// However this allows us to setup language level per file manually
// in case when it is LightVirtualFile
final LanguageLevel level = virtualFile.getUserData(KEY);
if (level != null) return level;
if (ApplicationManager.getApplication().isUnitTestMode()) {
final LanguageLevel languageLevel = FORCE_LANGUAGE_LEVEL;
if (languageLevel != null) {
return languageLevel;
}
}
}
return getDefault();
}
@NotNull
public static LanguageLevel forElement(@NotNull PsiElement element) {
final PsiFile containingFile = element.getContainingFile();
@@ -22,7 +22,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
@@ -35,7 +34,10 @@ import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.impl.PyStringLiteralExpressionImpl;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.PyTypeChecker;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -230,11 +232,7 @@ public class ConvertFormatOperatorToMethodIntention extends BaseIntentionAction
if (binaryExpression == null) {
return false;
}
final VirtualFile virtualFile = binaryExpression.getContainingFile().getVirtualFile();
if (virtualFile == null) {
return false;
}
final LanguageLevel languageLevel = LanguageLevel.forFile(virtualFile);
final LanguageLevel languageLevel = LanguageLevel.forElement(binaryExpression);
if (languageLevel.isOlderThan(LanguageLevel.PYTHON26)) {
return false;
}
@@ -129,7 +129,7 @@ public class PyUserSkeletonsUtil {
final PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(directory);
PsiElement fileSkeleton = new QualifiedNameResolverImpl(qName).resolveModuleAt(psiDirectory);
if (fileSkeleton instanceof PsiDirectory) {
fileSkeleton = PyUtil.getPackageElement((PsiDirectory)fileSkeleton);
fileSkeleton = PyUtil.getPackageElement((PsiDirectory)fileSkeleton, foothold);
}
if (fileSkeleton instanceof PyFile) {
cache.put(cacheQName, Collections.singletonList(fileSkeleton));
@@ -21,10 +21,11 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.FactoryMap;
import com.jetbrains.python.console.parsing.PyConsoleHighlightingLexer;
import com.jetbrains.python.console.PydevConsoleRunner;
import com.jetbrains.python.lexer.PythonHighlightingLexer;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
@@ -51,11 +52,10 @@ public class PySyntaxHighlighterFactory extends SyntaxHighlighterFactory {
};
@NotNull
public SyntaxHighlighter getSyntaxHighlighter(final Project project, final VirtualFile virtualFile) {
LanguageLevel languageLevel = virtualFile != null ? LanguageLevel.forFile(virtualFile) : LanguageLevel.getDefault();
if (virtualFile != null && PydevConsoleRunner.isInPydevConsole(virtualFile)) {
return myConsoleMap.get(languageLevel);
}
return myMap.get(languageLevel);
public SyntaxHighlighter getSyntaxHighlighter(@Nullable final Project project, @Nullable final VirtualFile virtualFile) {
final LanguageLevel level = project != null && virtualFile != null ?
PyUtil.getLanguageLevelForVirtualFile(project, virtualFile) :
LanguageLevel.getDefault();
return myMap.get(level);
}
}
@@ -21,19 +21,18 @@ import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiElementFilter;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.Processor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.inspections.quickfix.RenameParameterQuickFix;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyNoneType;
import com.jetbrains.python.psi.types.PyType;
@@ -79,13 +78,7 @@ public class PyPropertyDefinitionInspection extends PyInspection {
super(holder, session);
PsiFile psiFile = session.getFile();
// save us continuous checks for level, module, stc
LanguageLevel level = null;
if (psiFile != null) {
VirtualFile vfile = psiFile.getVirtualFile();
if (vfile != null) level = LanguageLevel.forFile(vfile);
}
if (level == null) level = LanguageLevel.getDefault();
myLevel = level;
myLevel = LanguageLevel.forElement(psiFile);
// string classes
final List<PyClass> string_classes = new ArrayList<PyClass>(2);
final PyBuiltinCache builtins = PyBuiltinCache.getInstance(psiFile);
@@ -17,7 +17,6 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
@@ -52,11 +51,7 @@ public class PyRaisingNewStyleClassInspection extends PyInspection {
@Override
public void visitPyRaiseStatement(PyRaiseStatement node) {
final VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
if (virtualFile == null) {
return;
}
if (LanguageLevel.forFile(virtualFile).isAtLeast(LanguageLevel.PYTHON25)) {
if (LanguageLevel.forElement(node).isAtLeast(LanguageLevel.PYTHON25)) {
return;
}
final PyExpression[] expressions = node.getExpressions();
@@ -17,7 +17,6 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.*;
@@ -67,8 +66,7 @@ public class PyTupleAssignmentBalanceInspection extends PyInspection {
PyExpression[] elements = ((PyTupleExpression) lhsExpression).getElements();
boolean containsStarExpression = false;
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
if (virtualFile != null && LanguageLevel.forFile(virtualFile).isPy3K()) {
if (LanguageLevel.forElement(node).isPy3K()) {
for (PyExpression target: elements) {
if (target instanceof PyStarExpression) {
if (containsStarExpression) {
@@ -116,7 +116,7 @@ public class AddFunctionQuickFix implements LocalQuickFix {
}
}
// else: no arglist, use empty args
PyFunction function = builder.buildFunction(project, LanguageLevel.forFile(file.getVirtualFile()));
PyFunction function = builder.buildFunction(project, LanguageLevel.forElement(file));
// add to the bottom
function = (PyFunction) file.add(function);
@@ -23,13 +23,17 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
@@ -66,6 +70,7 @@ import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.refactoring.classes.PyDependenciesComparator;
import com.jetbrains.python.refactoring.classes.extractSuperclass.PyExtractSuperclassHelper;
import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -733,6 +738,52 @@ public class PyUtil {
return pyClass.findMethodByName(PyNames.INIT, false);
}
/**
* Returns Python language level for a virtual file.
*
* @see {@link LanguageLevel#forElement}
*/
@NotNull
public static LanguageLevel getLanguageLevelForVirtualFile(@NotNull Project project,
@NotNull VirtualFile virtualFile) {
if (virtualFile instanceof VirtualFileWindow)
virtualFile = ((VirtualFileWindow)virtualFile).getDelegate();
// Most of the cases should be handled by this one, PyLanguageLevelPusher pushes folders only
final VirtualFile folder = virtualFile.getParent();
if (folder != null) {
final LanguageLevel level = folder.getUserData(LanguageLevel.KEY);
if (level != null) return level;
}
else {
// However this allows us to setup language level per file manually
// in case when it is LightVirtualFile
final LanguageLevel level = virtualFile.getUserData(LanguageLevel.KEY);
if (level != null) return level;
if (ApplicationManager.getApplication().isUnitTestMode()) {
final LanguageLevel languageLevel = LanguageLevel.FORCE_LANGUAGE_LEVEL;
if (languageLevel != null) {
return languageLevel;
}
}
}
return guessLanguageLevel(project);
}
private static LanguageLevel guessLanguageLevel(@NotNull Project project) {
final ModuleManager moduleManager = ModuleManager.getInstance(project);
if (moduleManager != null) {
for (Module projectModule : moduleManager.getModules()) {
final Sdk sdk = PythonSdkType.findPythonSdk(projectModule);
if (sdk != null) {
return PythonSdkType.getLanguageLevelForSdk(sdk);
}
}
}
return LanguageLevel.getDefault();
}
public static class KnownDecoratorProviderHolder {
public static PyKnownDecoratorProvider[] KNOWN_DECORATOR_PROVIDERS = Extensions.getExtensions(PyKnownDecoratorProvider.EP_NAME);
@@ -793,11 +844,14 @@ public class PyUtil {
return target;
}
public static boolean isPackage(@NotNull PsiDirectory directory) {
public static boolean isPackage(@NotNull PsiDirectory directory, @Nullable PsiElement anchor) {
if (turnDirIntoInit(directory) != null) {
return true;
}
if (LanguageLevel.forFile(directory.getVirtualFile()).isAtLeast(LanguageLevel.PYTHON33)) {
final LanguageLevel level = anchor != null ?
LanguageLevel.forElement(anchor) :
getLanguageLevelForVirtualFile(directory.getProject(), directory.getVirtualFile());
if (level.isAtLeast(LanguageLevel.PYTHON33)) {
return true;
}
return hasNamespacePackageFile(directory);
@@ -808,8 +862,8 @@ public class PyUtil {
}
@Nullable
public static PsiElement getPackageElement(@NotNull PsiDirectory directory) {
if (isPackage(directory)) {
public static PsiElement getPackageElement(@NotNull PsiDirectory directory, @Nullable PsiElement anchor) {
if (isPackage(directory, anchor)) {
final PsiElement init = turnDirIntoInit(directory);
if (init != null) {
return init;
@@ -663,10 +663,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
// EA-32381: A tree-based instance may not have a parent element somehow, so getContainingFile() may be not appropriate
final PsiFile file = getParentByStub() != null ? getContainingFile() : null;
if (file != null) {
final VirtualFile vfile = file.getVirtualFile();
if (vfile != null) {
level = LanguageLevel.forFile(vfile);
}
level = LanguageLevel.forElement(file);
}
final boolean useAdvancedSyntax = level.isAtLeast(LanguageLevel.PYTHON26);
final Property local = processPropertiesInClass(name, filter, useAdvancedSyntax);
@@ -294,7 +294,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
if (virtualFile == null) {
virtualFile = getViewProvider().getVirtualFile();
}
return LanguageLevel.forFile(virtualFile);
return PyUtil.getLanguageLevelForVirtualFile(getProject(), virtualFile);
}
public Icon getIcon(int flags) {
@@ -143,7 +143,7 @@ public class PyImportedModule extends LightElement implements NameDefiner {
element = ResolveImportUtil.resolveModuleInRoots(getImportedPrefix(), getContainingFile());
}
if (element instanceof PsiDirectory) {
return PyUtil.getPackageElement((PsiDirectory)element);
return PyUtil.getPackageElement((PsiDirectory)element, this);
}
return element;
}
@@ -427,7 +427,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
}
else if (resolveResult instanceof PsiDirectory) {
final PsiDirectory directory = (PsiDirectory)resolveResult;
if (PyUtil.isPackage(directory) && directory == element) {
if (PyUtil.isPackage(directory, null) && directory == element) {
return true;
}
}
@@ -132,7 +132,7 @@ public class ResolveImportUtil {
throw new PsiInvalidElementAccessException(candidate, "Got an invalid candidate from resolveImportSourceCandidates(): " + candidate.getClass());
}
if (candidate instanceof PsiDirectory) {
candidate = PyUtil.getPackageElement((PsiDirectory)candidate);
candidate = PyUtil.getPackageElement((PsiDirectory)candidate, importStatement);
}
PsiElement result = resolveChild(candidate, name, file, false, true);
if (result != null) {
@@ -326,7 +326,7 @@ public class ResolveImportUtil {
if (referencedName == null) return null;
final PsiDirectory subdir = dir.findSubdirectory(referencedName);
if (subdir != null && (!checkForPackage || PyUtil.isPackage(subdir))) {
if (subdir != null && (!checkForPackage || PyUtil.isPackage(subdir, containingFile))) {
return subdir;
}
@@ -358,7 +358,7 @@ public class ResolveImportUtil {
ResolveResultList ret = new ResolveResultList();
for (PsiElement target : targets) {
if (target instanceof PsiDirectory) {
target = PyUtil.getPackageElement((PsiDirectory)target);
target = PyUtil.getPackageElement((PsiDirectory)target, null);
}
if (target != null) { // Ignore non-package dirs, worthless
int rate = RatedResolveResult.RATE_HIGH;
@@ -450,7 +450,7 @@ public class PyTypeParser {
break;
}
if (module instanceof PsiDirectory) {
module = PyUtil.getPackageElement((PsiDirectory)module);
module = PyUtil.getPackageElement((PsiDirectory)module, myAnchor);
}
if (module instanceof PyTypedElement) {
final PyType moduleType = context.getType((PyTypedElement)module);
@@ -23,11 +23,9 @@ import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ex.ProblemDescriptorImpl;
import com.intellij.codeInspection.ex.QuickFixWrapper;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -44,7 +42,7 @@ public class UnsupportedFeatures extends CompatibilityVisitor {
@Override
public void visitPyElement(PyElement node) {
setVersionsToProcess(Arrays.asList(getLanguageLevel(node)));
setVersionsToProcess(Arrays.asList(LanguageLevel.forElement(node)));
}
@Override
@@ -70,15 +68,6 @@ public class UnsupportedFeatures extends CompatibilityVisitor {
getHolder().createWarningAnnotation(range, message);
}
@NotNull
private static LanguageLevel getLanguageLevel(PyElement node) {
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
if (virtualFile != null) {
return LanguageLevel.forFile(virtualFile);
}
return LanguageLevel.getDefault();
}
private static IntentionAction createIntention(PsiElement node, String message, LocalQuickFix fix) {
return createIntention(node, node.getTextRange(), message, fix);
}