diff options
Diffstat (limited to 'python/src/com/jetbrains/python')
20 files changed, 281 insertions, 130 deletions
diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyBracketProtectingCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyBracketProtectingCompletionContributor.java deleted file mode 100644 index 766e5be81f3e..000000000000 --- a/python/src/com/jetbrains/python/codeInsight/completion/PyBracketProtectingCompletionContributor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2000-2013 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.codeInsight.completion; - -import com.intellij.codeInsight.completion.CompletionContributor; -import com.intellij.codeInsight.completion.CompletionInitializationContext; -import com.intellij.psi.PsiReference; -import com.jetbrains.python.psi.impl.references.PyOperatorReference; -import org.jetbrains.annotations.NotNull; - -/** - * @author yole - */ -public class PyBracketProtectingCompletionContributor extends CompletionContributor { - @Override - public void beforeCompletion(@NotNull CompletionInitializationContext context) { - PsiReference ref = context.getFile().findReferenceAt(context.getSelectionEndOffset()); - if (ref instanceof PyOperatorReference) { - context.setReplacementOffset(context.getIdentifierEndOffset()); - } - } -} diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java index 725cd2d9bf4d..e27f2a638899 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.codeInsight.editorActions.smartEnter; +import com.google.common.collect.ImmutableList; import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.openapi.diagnostic.Logger; @@ -48,25 +49,22 @@ import java.util.List; */ public class PySmartEnterProcessor extends SmartEnterProcessor { private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor"); - private static final List<PyFixer> ourFixers = new ArrayList<PyFixer>(); - private static final List<EnterProcessor> ourProcessors = new ArrayList<EnterProcessor>(); - - static { - ourFixers.add(new PyStringLiteralFixer()); - ourFixers.add(new PyParenthesizedFixer()); - ourFixers.add(new PyMissingBracesFixer()); - ourFixers.add(new PyConditionalStatementPartFixer()); - ourFixers.add(new PyUnconditionalStatementPartFixer()); - ourFixers.add(new PyForPartFixer()); - ourFixers.add(new PyExceptFixer()); - ourFixers.add(new PyArgumentListFixer()); - ourFixers.add(new PyParameterListFixer()); - ourFixers.add(new PyFunctionFixer()); - ourFixers.add(new PyClassFixer()); - - ourProcessors.add(new PyCommentBreakerEnterProcessor()); - ourProcessors.add(new PyPlainEnterProcessor()); - } + private static final List<PyFixer> ourFixers = ImmutableList.<PyFixer>builder() + .add(new PyStringLiteralFixer()) + .add(new PyParenthesizedFixer()) + .add(new PyMissingBracesFixer()) + .add(new PyConditionalStatementPartFixer()) + .add(new PyUnconditionalStatementPartFixer()) + .add(new PyForPartFixer()) + .add(new PyExceptFixer()) + .add(new PyArgumentListFixer()) + .add(new PyParameterListFixer()) + .add(new PyFunctionFixer()) + .add(new PyClassFixer()) + .add(new PyWithFixer()) + .build(); + private static final List<EnterProcessor> ourProcessors = ImmutableList.of(new PyCommentBreakerEnterProcessor(), + new PyPlainEnterProcessor()); private static class TooManyAttemptsException extends Exception { } diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java index d6717905a034..ac2e31252dcf 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java @@ -20,10 +20,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.codeInsight.editorActions.smartEnter.SmartEnterUtil; -import com.jetbrains.python.psi.PyClass; -import com.jetbrains.python.psi.PyFunction; -import com.jetbrains.python.psi.PyStatementList; -import com.jetbrains.python.psi.PyStatementPart; +import com.jetbrains.python.psi.*; import org.jetbrains.annotations.Nullable; /** @@ -43,10 +40,14 @@ public class PyPlainEnterProcessor implements EnterProcessor { } else if (psiElement instanceof PyClass) { return ((PyClass)psiElement).getStatementList(); - } else { - final CaretModel caretModel = editor.getCaretModel(); - final PsiElement atCaret = psiElement.getContainingFile().findElementAt(caretModel.getOffset()); - PyStatementPart statementPart = PsiTreeUtil.getParentOfType(atCaret, PyStatementPart.class); + } + else if (psiElement instanceof PyWithStatement) { + return PsiTreeUtil.getChildOfType(psiElement, PyStatementList.class); + } + else { + final CaretModel caretModel = editor.getCaretModel(); + final PsiElement atCaret = psiElement.getContainingFile().findElementAt(caretModel.getOffset()); + final PyStatementPart statementPart = PsiTreeUtil.getParentOfType(atCaret, PyStatementPart.class); if (statementPart != null) { return statementPart.getStatementList(); } @@ -55,7 +56,7 @@ public class PyPlainEnterProcessor implements EnterProcessor { } public boolean doEnter(Editor editor, PsiElement psiElement, boolean isModified) { - PyStatementList statementList = getStatementList(psiElement, editor); + final PyStatementList statementList = getStatementList(psiElement, editor); if (statementList != null && statementList.getStatements().length == 0) { SmartEnterUtil.plainEnter(editor); //editor.getCaretModel().moveToOffset(statementList.getTextRange().getEndOffset()); diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java new file mode 100644 index 000000000000..b6d099ef7cb5 --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2013 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.codeInsight.editorActions.smartEnter.fixers; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; +import com.jetbrains.python.psi.PyElementType; +import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.PyWithItem; +import com.jetbrains.python.psi.PyWithStatement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.jetbrains.python.psi.PyUtil.sure; + +/** + * @author Mikhail Golubev + */ +public class PyWithFixer implements PyFixer { + public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { + if (psiElement instanceof PyWithStatement) { + final PyWithStatement withStatement = (PyWithStatement)psiElement; + final PsiElement colonToken = getFirstChildOfType(psiElement, PyTokenTypes.COLON); + final PsiElement withToken = getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD); + final Document document = editor.getDocument(); + if (colonToken == null) { + int insertAt = sure(withToken).getTextRange().getEndOffset(); + String textToInsert = ":"; + final PyWithItem[] withItems = withStatement.getWithItems(); + final PyWithItem lastItem = withItems.length != 0 ? withItems[withItems.length - 1] : null; + if (lastItem == null || lastItem.getExpression() == null) { + textToInsert = " :"; + processor.registerUnresolvedError(insertAt + 1); + } + else { + final PyExpression expression = lastItem.getExpression(); + insertAt = expression.getTextRange().getEndOffset(); + final PsiElement asToken = getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD); + if (asToken != null) { + insertAt = asToken.getTextRange().getEndOffset(); + final PyExpression target = lastItem.getTarget(); + if (target != null) { + insertAt = target.getTextRange().getEndOffset(); + } + else { + textToInsert = " :"; + processor.registerUnresolvedError(insertAt + 1); + } + } + } + document.insertString(insertAt, textToInsert); + } + } + } + + @Nullable + private static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) { + final ASTNode child = element.getNode().findChildByType(type); + return child != null ? child.getPsi() : null; + } +} diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java index 3df0a3edf390..0ba35edad8bf 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java @@ -290,7 +290,10 @@ public class ConvertFormatOperatorToMethodIntention extends BaseIntentionAction } } else target.append("(").append(paramText).append(")"); // tuple is ok as is - element.replace(elementGenerator.createExpressionFromText(LanguageLevel.forElement(element), target.toString())); + // Correctly handle multiline implicitly concatenated string literals (PY-9176) + target.insert(0, '(').append(')'); + final PyExpression parenthesized = elementGenerator.createExpressionFromText(LanguageLevel.forElement(element), target.toString()); + element.replace(sure(((PyParenthesizedExpression)parenthesized).getContainedExpression())); } private static String getSeparator(PyStringLiteralExpression leftExpression) { diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java index ba2f137751a4..3d77ac4f62b1 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -52,8 +52,8 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.CharsetToolkit; @@ -360,7 +360,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC manager.createRemoteProcess(getProject(), myRemoteCredentials, mappings, commandLine, true); - Pair<Integer, Integer> remotePorts = getRemotePortsFromProcess(remoteProcess); + Couple<Integer> remotePorts = getRemotePortsFromProcess(remoteProcess); remoteProcess.addLocalTunnel(myPorts[0], myRemoteCredentials.getHost(), remotePorts.first); remoteProcess.addRemoteTunnel(remotePorts.second, "localhost", myPorts[1]); @@ -374,10 +374,10 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC } } - private static Pair<Integer, Integer> getRemotePortsFromProcess(RemoteSshProcess process) throws ExecutionException { + private static Couple<Integer> getRemotePortsFromProcess(RemoteSshProcess process) throws ExecutionException { Scanner s = new Scanner(process.getInputStream()); - return Pair.create(readInt(s, process), readInt(s, process)); + return Couple.of(readInt(s, process), readInt(s, process)); } private static int readInt(Scanner s, Process process) throws ExecutionException { diff --git a/python/src/com/jetbrains/python/inspections/quickfix/GenerateBinaryStubsFix.java b/python/src/com/jetbrains/python/inspections/quickfix/GenerateBinaryStubsFix.java index 3e13332c2616..7d087bd3eb08 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/GenerateBinaryStubsFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/GenerateBinaryStubsFix.java @@ -19,12 +19,15 @@ import com.google.common.collect.Lists; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.execution.process.ProcessOutput; +import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.application.Result; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; +import com.intellij.openapi.progress.Task.Backgroundable; import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; @@ -65,6 +68,7 @@ public class GenerateBinaryStubsFix implements LocalQuickFix { /** * Generates pack of fixes available for some unresolved import statement. * Be sure to call {@link #isApplicable(com.jetbrains.python.psi.PyImportStatementBase)} first to make sure this statement is supported + * * @param importStatementBase statement to fix * @return pack of fixes */ @@ -73,14 +77,14 @@ public class GenerateBinaryStubsFix implements LocalQuickFix { final List<String> names = importStatementBase.getFullyQualifiedObjectNames(); final List<GenerateBinaryStubsFix> result = new ArrayList<GenerateBinaryStubsFix>(names.size()); for (final String qualifiedName : names) { - result.add(new GenerateBinaryStubsFix(importStatementBase, qualifiedName)); + result.add(new GenerateBinaryStubsFix(importStatementBase, qualifiedName)); } return result; } /** * @param importStatementBase statement to fix - * @param qualifiedName name should be fixed (one of {@link com.jetbrains.python.psi.PyImportStatementBase#getFullyQualifiedObjectNames()}) + * @param qualifiedName name should be fixed (one of {@link com.jetbrains.python.psi.PyImportStatementBase#getFullyQualifiedObjectNames()}) */ private GenerateBinaryStubsFix(@NotNull final PyImportStatementBase importStatementBase, @NotNull final String qualifiedName) { myQualifiedName = qualifiedName; @@ -102,15 +106,34 @@ public class GenerateBinaryStubsFix implements LocalQuickFix { @Override public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { final PsiFile file = descriptor.getPsiElement().getContainingFile(); - final String folder = file.getContainingDirectory().getVirtualFile().getCanonicalPath(); + final Backgroundable backgroundable = getFixTask(file); + ProgressManager.getInstance().runProcessWithProgressAsynchronously(backgroundable, new BackgroundableProcessIndicator(backgroundable)); + } - final Task.Backgroundable backgroundable = new Task.Backgroundable(project, "Generating skeletons for binary module", false) { + + /** + * Returns fix task that is used to generate stubs + * @param fileToRunTaskIn file where task should run + * @return task itself + */ + @NotNull + public Backgroundable getFixTask(@NotNull final PsiFile fileToRunTaskIn) { + final Project project = fileToRunTaskIn.getProject(); + final String folder = fileToRunTaskIn.getContainingDirectory().getVirtualFile().getCanonicalPath(); + return new Task.Backgroundable(project, "Generating skeletons for binary module", false) { @Override public void run(@NotNull ProgressIndicator indicator) { indicator.setIndeterminate(true); - final List<String> assemblyRefs = collectAssemblyReferences(file); + + final List<String> assemblyRefs = new ReadAction<List<String>>() { + @Override + protected void run(@NotNull Result<List<String>> result) throws Throwable { + result.setResult(collectAssemblyReferences(fileToRunTaskIn)); + } + }.execute().getResultObject(); + try { final PySkeletonRefresher refresher = new PySkeletonRefresher(project, null, mySdk, null, null, folder); @@ -133,7 +156,6 @@ public class GenerateBinaryStubsFix implements LocalQuickFix { } } }; - ProgressManager.getInstance().runProcessWithProgressAsynchronously(backgroundable, new BackgroundableProcessIndicator(backgroundable)); } private boolean generateSkeletonsForList(@NotNull final PySkeletonRefresher refresher, @@ -185,8 +207,8 @@ public class GenerateBinaryStubsFix implements LocalQuickFix { // TODO: What if user loads it not by literal? We need to ask user for list of DLLs if (node.isCalleeText("AddReference", "AddReferenceByPartialName", "AddReferenceByName")) { final PyExpression[] args = node.getArguments(); - if (args.length == 1 && args [0] instanceof PyStringLiteralExpression) { - result.add(((PyStringLiteralExpression) args [0]).getStringValue()); + if (args.length == 1 && args[0] instanceof PyStringLiteralExpression) { + result.add(((PyStringLiteralExpression)args[0]).getStringValue()); } } } diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index fac391abdff7..c0fb3c1d620d 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -464,7 +464,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } if (expr.isQualified()) { final PyClassTypeImpl object_type = (PyClassTypeImpl)PyBuiltinCache.getInstance(node).getObjectType(); - if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refName)) return; + if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refName)){ + return; + } } else { if (PyUnreachableCodeInspection.hasAnyInterruptedControlFlowPaths(expr)) { @@ -494,7 +496,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } // unqualified: // may be module's - if (PyModuleType.getPossibleInstanceMembers().contains(refName)) return; + if (PyModuleType.getPossibleInstanceMembers().contains(refName)) { + return; + } // may be a "try: import ..."; not an error not to resolve if (( PsiTreeUtil.getParentOfType( diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 359e497f21c8..65d95eb62713 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -795,14 +795,22 @@ public class PyPackageManagerImpl extends PyPackageManager { private String getHelperPath(String helper) { String helperPath; final SdkAdditionalData sdkData = mySdk.getSdkAdditionalData(); - if (sdkData instanceof RemoteSdkCredentials) { - final RemoteSdkCredentials remoteSdkCredentials = (RemoteSdkCredentials)sdkData; - if (!StringUtil.isEmpty(remoteSdkCredentials.getHelpersPath())) { - helperPath = new RemoteFile(remoteSdkCredentials.getHelpersPath(), - helper).getPath(); + if (sdkData instanceof PyRemoteSdkAdditionalDataBase) { + PyRemoteSdkAdditionalDataBase remoteSdkData = (PyRemoteSdkAdditionalDataBase)mySdk.getSdkAdditionalData(); + + try { + final RemoteSdkCredentials remoteSdkCredentials = remoteSdkData.getRemoteSdkCredentials(false); + if (!StringUtil.isEmpty(remoteSdkCredentials.getHelpersPath())) { + helperPath = new RemoteFile(remoteSdkCredentials.getHelpersPath(), + helper).getPath(); + } + else { + helperPath = null; + } } - else { + catch (Exception e) { helperPath = null; + LOG.error(e); } } else { @@ -833,25 +841,26 @@ public class PyPackageManagerImpl extends PyPackageManager { catch (final ExecutionException e) { if (e.getCause() instanceof VagrantNotStartedException) { throw new PyExternalProcessException(ERROR_VAGRANT_NOT_LAUNCHED, helperPath, args, "Vagrant instance is down. <a href=\"" + - LAUNCH_VAGRANT + - "\">Launch vagrant</a>").withHandler(LAUNCH_VAGRANT, new Runnable() { - @Override - public void run() { - final PythonRemoteInterpreterManager manager = PythonRemoteInterpreterManager.getInstance(); - if (manager != null) { - - try { - manager.runVagrant(((VagrantNotStartedException)e.getCause()).getVagrantFolder()); - clearCaches(); - - } - catch (ExecutionException e1) { - throw new RuntimeException(e1); + LAUNCH_VAGRANT + + "\">Launch vagrant</a>") + .withHandler(LAUNCH_VAGRANT, new Runnable() { + @Override + public void run() { + final PythonRemoteInterpreterManager manager = PythonRemoteInterpreterManager.getInstance(); + if (manager != null) { + + try { + manager.runVagrant(((VagrantNotStartedException)e.getCause()).getVagrantFolder()); + clearCaches(); + } + catch (ExecutionException e1) { + throw new RuntimeException(e1); + } } } - } - }); - } else { + }); + } + else { throw new PyExternalProcessException(ERROR_REMOTE_ACCESS, helperPath, args, e.getMessage()); } } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java index 3bfcc497cac9..31258fa69ea5 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java @@ -181,7 +181,7 @@ public class PyPackageUtil { VfsUtilCore.visitChildrenRecursively(root, new VirtualFileVisitor() { @Override public boolean visitFile(@NotNull VirtualFile file) { - if (!fileIndex.isIgnored(file) && file.isDirectory() && file.findChild(PyNames.INIT_DOT_PY) != null) { + if (!fileIndex.isExcluded(file) && file.isDirectory() && file.findChild(PyNames.INIT_DOT_PY) != null) { results.add(VfsUtilCore.getRelativePath(file, root, '.')); } return true; diff --git a/python/src/com/jetbrains/python/projectView/PyRemoteLibrariesNode.java b/python/src/com/jetbrains/python/projectView/PyRemoteLibrariesNode.java index 62de7ea14daf..c5b0af7103f3 100644 --- a/python/src/com/jetbrains/python/projectView/PyRemoteLibrariesNode.java +++ b/python/src/com/jetbrains/python/projectView/PyRemoteLibrariesNode.java @@ -19,16 +19,16 @@ import com.google.common.base.Function; import com.google.common.base.Predicates; import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; +import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.ide.projectView.PresentationData; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; +import com.intellij.psi.*; import com.intellij.util.PlatformIcons; import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase; import com.jetbrains.python.sdk.PySdkUtil; @@ -75,11 +75,16 @@ public class PyRemoteLibrariesNode extends PsiDirectoryNode { return FluentIterable.from(Lists.newArrayList(getValue().getChildren())).transform(new Function<PsiElement, AbstractTreeNode>() { @Override public AbstractTreeNode apply(PsiElement input) { - if (input instanceof PsiDirectory) { - PsiDirectory directory = (PsiDirectory)input; - if (myRemoteSdkData.getPathMappings().canReplaceLocal((directory.getVirtualFile().getPath()))) { - return new PyRemoteRootNode(myRemoteSdkData.getPathMappings().convertToRemote(directory.getVirtualFile().getPath()), - getProject(), directory, getSettings()); + if (input instanceof PsiFileSystemItem) { + String path = ((PsiFileSystemItem)input).getVirtualFile().getPath(); + + + PsiDirectory dir = input instanceof PsiDirectory ? (PsiDirectory)input : getDirectoryForJar((PsiFile)input); + + + if (myRemoteSdkData.getPathMappings().canReplaceLocal(path)) { + return new PyRemoteRootNode(myRemoteSdkData.getPathMappings().convertToRemote(path), + getProject(), dir, getSettings()); } } @@ -88,6 +93,26 @@ public class PyRemoteLibrariesNode extends PsiDirectoryNode { }).filter(Predicates.notNull()).toList(); } + @Nullable + private PsiDirectory getDirectoryForJar(PsiFile input) { + VirtualFile jarRoot = getJarRoot(input); + if (myProject != null && jarRoot != null) { + return PsiManager.getInstance(myProject).findDirectory(jarRoot); + } + else { + return null; + } + } + + @Nullable + private static VirtualFile getJarRoot(PsiFile input) { + final VirtualFile file = input.getVirtualFile(); + if (file == null || !file.isValid() || !(file.getFileType() instanceof ArchiveFileType)) { + return null; + } + return JarFileSystem.getInstance().getJarRootForLocalFile(file); + } + public static class PyRemoteRootNode extends PsiDirectoryNode { private String myRemotePath; diff --git a/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java b/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java index 6153bc64146d..8e4889498bca 100644 --- a/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java +++ b/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java @@ -28,6 +28,8 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SdkTypeId; import com.intellij.openapi.roots.JdkOrderEntry; import com.intellij.openapi.roots.LibraryOrSdkOrderEntry; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -50,7 +52,9 @@ import java.util.List; public class PyTreeStructureProvider implements SelectableTreeStructureProvider, DumbAware { @NotNull @Override - public Collection<AbstractTreeNode> modify(@NotNull AbstractTreeNode parent, @NotNull Collection<AbstractTreeNode> children, ViewSettings settings) { + public Collection<AbstractTreeNode> modify(@NotNull AbstractTreeNode parent, + @NotNull Collection<AbstractTreeNode> children, + ViewSettings settings) { final Project project = parent.getProject(); final Sdk sdk = getPythonSdk(parent); if (sdk != null && project != null) { @@ -111,7 +115,15 @@ public class PyTreeStructureProvider implements SelectableTreeStructureProvider, if (directory.getVirtualFile().equals(PyUserSkeletonsUtil.getUserSkeletonsDirectory())) { continue; } - PsiDirectory dirParent = directory.getParent(); + VirtualFile dir = directory.getVirtualFile(); + if (dir.getFileSystem() instanceof JarFileSystem) { + dir = ((JarFileSystem)directory.getVirtualFile().getFileSystem()).getLocalVirtualFileFor(directory.getVirtualFile()); + } + if (dir == null) { + continue; + } + VirtualFile dirParent = dir.getParent(); + if (dirParent != null && dirParent.getName().equals(PythonSdkType.SKELETON_DIR_NAME)) { continue; } @@ -120,7 +132,7 @@ public class PyTreeStructureProvider implements SelectableTreeStructureProvider, continue; } if (dirParent != null) { - PsiDirectory grandParent = dirParent.getParent(); + VirtualFile grandParent = dirParent.getParent(); if (grandParent != null && grandParent.getName().equals(PythonSdkType.REMOTE_SOURCES_DIR_NAME)) { continue; @@ -158,8 +170,8 @@ public class PyTreeStructureProvider implements SelectableTreeStructureProvider, } } if (parents.size() > 0) { - return parents.get(parents.size()-1); + return parents.get(parents.size() - 1); } - return element.getContainingFile(); + return element.getContainingFile(); } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java index 307ac8e22841..4011c233e38d 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java @@ -15,6 +15,8 @@ */ package com.jetbrains.python.psi.impl; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; import com.intellij.lang.ASTNode; import com.intellij.navigation.ItemPresentation; import com.intellij.psi.PsiElement; @@ -50,7 +52,11 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo for (PsiElement importedFile : new HashSet<PsiElement>(importedFiles)) { // resolver gives lots of duplicates final PsiElement source = PyUtil.turnDirIntoInit(importedFile); if (source instanceof PyFile) { - chain.add(((PyFile) source).iterateNames()); + Iterable<PyElement> declaredNames = ((PyFile)source).iterateNames(); + if (((PyFile)source).getDunderAll() == null) { + declaredNames = excludeUnderscoredNames(declaredNames); + } + chain.add(declaredNames); } } return chain; @@ -58,6 +64,19 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo return Collections.emptyList(); } + private static Iterable<PyElement> excludeUnderscoredNames(Iterable<PyElement> declaredNames) { + return Iterables.filter(declaredNames, new Predicate<PyElement>() { + @Override + public boolean apply(@Nullable PyElement input) { + final String name = input != null ? input.getName() : null; + if (name != null && name.startsWith("_")) { + return false; + } + return true; + } + }); + } + @Nullable public PsiElement getElementNamed(final String name) { if (PyUtil.isClassPrivateName(name)) { @@ -76,7 +95,7 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo final PsiElement result = results != null && !results.isEmpty() ? results.get(0).getElement() : null; if (result != null) { final List<String> all = sourceFile.getDunderAll(); - if (all != null && !all.contains(name)) { + if (all != null ? !all.contains(name) : name.startsWith("_")) { continue; } return result; diff --git a/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java b/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java index 136a7073bb8b..7e15cab6ffda 100644 --- a/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java +++ b/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java @@ -146,7 +146,7 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev private static final FileAttribute PERSISTENCE = new FileAttribute("python_language_level_persistence", 2, true); - public void persistAttribute(@NotNull VirtualFile fileOrDir, @NotNull LanguageLevel level) throws IOException { + public void persistAttribute(@NotNull Project project, @NotNull VirtualFile fileOrDir, @NotNull LanguageLevel level) throws IOException { final DataInputStream iStream = PERSISTENCE.readAttribute(fileOrDir); if (iStream != null) { try { @@ -164,7 +164,7 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev for (VirtualFile child : fileOrDir.getChildren()) { if (!child.isDirectory() && PythonFileType.INSTANCE.equals(child.getFileType())) { - PushedFilePropertiesUpdater.filePropertiesChanged(child); + PushedFilePropertiesUpdater.getInstance(project).filePropertiesChanged(child); } } } @@ -247,7 +247,7 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev return false; } if (file.isDirectory()) { - PushedFilePropertiesUpdater.findAndUpdateValue(project, file, PythonLanguageLevelPusher.this, languageLevel); + PushedFilePropertiesUpdater.getInstance(project).findAndUpdateValue(file, PythonLanguageLevelPusher.this, languageLevel); } if (suppressSizeLimit) { SingleRootFileViewProvider.doNotCheckFileSizeLimit(file); diff --git a/python/src/com/jetbrains/python/psi/impl/stubs/PyFileStubBuilder.java b/python/src/com/jetbrains/python/psi/impl/stubs/PyFileStubBuilder.java index 15a342151e6a..0858ff5056bb 100644 --- a/python/src/com/jetbrains/python/psi/impl/stubs/PyFileStubBuilder.java +++ b/python/src/com/jetbrains/python/psi/impl/stubs/PyFileStubBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull; * @author yole */ public class PyFileStubBuilder extends DefaultStubBuilder { + @NotNull @Override protected StubElement createStubForFile(@NotNull PsiFile file) { if (file instanceof PyFile) { diff --git a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java index bb58b68300e8..4b3adfd112f8 100644 --- a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java +++ b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java @@ -16,8 +16,11 @@ package com.jetbrains.python.psi.types; import com.intellij.psi.PsiElement; +import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; +import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.resolve.RatedResolveResult; import org.jetbrains.annotations.NotNull; @@ -71,12 +74,20 @@ public class PyFunctionType implements PyCallableType { @Nullable PyExpression location, @NotNull AccessDirection direction, @NotNull PyResolveContext resolveContext) { - return Collections.emptyList(); + final PyClassTypeImpl functionType = PyBuiltinCache.getInstance(getCallable()).getObjectType(PyNames.FAKE_FUNCTION); + if (functionType == null) { + return Collections.emptyList(); + } + return functionType.resolveMember(name, location, direction, resolveContext); } @Override public Object[] getCompletionVariants(String completionPrefix, PsiElement location, ProcessingContext context) { - return new Object[0]; + final PyClassTypeImpl functionType = PyBuiltinCache.getInstance(getCallable()).getObjectType(PyNames.FAKE_FUNCTION); + if (functionType == null) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + return functionType.getCompletionVariants(completionPrefix, location, context); } @Override diff --git a/python/src/com/jetbrains/python/psi/types/PyModuleType.java b/python/src/com/jetbrains/python/psi/types/PyModuleType.java index f2dc67c10c70..db5a9ba3f1ae 100644 --- a/python/src/com/jetbrains/python/psi/types/PyModuleType.java +++ b/python/src/com/jetbrains/python/psi/types/PyModuleType.java @@ -308,7 +308,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje return !(psiElement instanceof PyImportElement) || PsiTreeUtil.getParentOfType(psiElement, PyImportStatementBase.class) instanceof PyFromImportStatement; } - }, new PyUtil.UnderscoreFilter(0)); + }, null); if (suppressParentheses) { processor.suppressParentheses(); } diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index 5e3506b9e4c5..f194f359e1a9 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -56,7 +56,9 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.reference.SoftReference; -import com.intellij.remote.*; +import com.intellij.remote.CredentialsType; +import com.intellij.remote.RemoteSdkCredentialsHolder; +import com.intellij.remote.VagrantNotStartedException; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.NullableConsumer; @@ -993,9 +995,9 @@ public class PythonSdkType extends SdkType { } public static boolean isIncompleteRemote(Sdk sdk) { - if (sdk.getSdkAdditionalData() instanceof RemoteSdkCredentials) { + if (PySdkUtil.isRemote(sdk)) { //noinspection ConstantConditions - if (!((RemoteSdkCredentials)sdk.getSdkAdditionalData()).isInitialized()) { + if (!((PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData()).isInitialized()) { return true; } } diff --git a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java index 271afc6e8c2f..124003158038 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java @@ -57,6 +57,6 @@ public class PyRemoteSdkFlavor extends CPythonSdkFlavor { @Nullable private static String getExecutableName(String path) { - return RemoteFile.detectSystemByPath(path).createRemoteFile(path).getName(); + return RemoteFile.createRemoteFile(path).getName(); } } diff --git a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java index c115ba45c272..a7faa6ebb98f 100644 --- a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java +++ b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java @@ -145,7 +145,7 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat } final PyPep8Inspection inspection = (PyPep8Inspection)profile.getUnwrappedTool(PyPep8Inspection.KEY.toString(), file); final List<String> ignoredErrors = inspection.ignoredErrors; - final int margin = CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings().RIGHT_MARGIN; + final int margin = CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings().getRightMargin(file.getLanguage()); return new State(homePath, file.getText(), profile.getErrorLevel(key, file), ignoredErrors, margin); } |