Merge branch 'master' of git.labs.intellij.net:idea/ultimate

This commit is contained in:
Ekaterina Tuzova
2010-12-02 15:07:06 +03:00
27 changed files with 298 additions and 28 deletions
@@ -224,6 +224,8 @@
<editorSmartKeysConfigurable implementation="com.jetbrains.python.codeInsight.PySmartKeysOptions"/>
<psi.referenceContributor implementation="com.jetbrains.python.codeInsight.PyStdReferenceContributor"/>
<!-- Django -->
<codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.django.annotator.ViewMethodLineMarkerProvider"/>
<configurationType implementation="com.jetbrains.django.run.DjangoServerRunConfigurationType"/>
@@ -0,0 +1,38 @@
package com.jetbrains.python.codeInsight;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReferenceBase;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author yole
*/
public class PyDunderAllReference extends PsiReferenceBase<PyStringLiteralExpression> {
public PyDunderAllReference(@NotNull PyStringLiteralExpression element) {
super(element);
final List<TextRange> ranges = element.getStringValueTextRanges();
if (ranges.size() > 0) {
setRangeInElement(ranges.get(0));
}
}
@Override
public PsiElement resolve() {
final PyStringLiteralExpression element = getElement();
final String name = element.getStringValue();
PyFile containingFile = (PyFile) element.getContainingFile();
return containingFile.getElementNamed(name);
}
@NotNull
@Override
public Object[] getVariants() {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
}
@@ -0,0 +1,19 @@
package com.jetbrains.python.codeInsight;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceProvider;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class PyDunderAllReferenceProvider extends PsiReferenceProvider {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
return new PsiReference[] { new PyDunderAllReference((PyStringLiteralExpression) element) };
}
}
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.lookup.TailTypeDecorator;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.patterns.StandardPatterns;
import com.intellij.psi.*;
@@ -608,17 +609,13 @@ public class PyKeywordCompletionContributor extends PySeeingOriginalCompletionCo
);
}
// FIXME: conditions must be severely reworked
private void addExprElse() {
extend(
CompletionType.BASIC, psiElement()
.withLanguage(PythonLanguage.getInstance())
.and(INSIDE_EXPR_AFTER_IF)
.andNot(IN_IMPORT_STMT) // expressions there are not logical anyway
//.andNot(IN_PARAM_LIST)
.andNot(IN_DEFINITION)
.andNot(AFTER_QUALIFIER)
.afterLeafSkipping(psiElement().whitespace(),
psiElement().inside(psiElement(PyConditionalExpression.class))
.and(psiElement().afterLeaf("if")))
,
new CompletionProvider<CompletionParameters>() {
protected void addCompletions(@NotNull final CompletionParameters parameters,
@@ -647,7 +644,7 @@ public class PyKeywordCompletionContributor extends PySeeingOriginalCompletionCo
addImportInFrom();
addPy3kLiterals();
//addExprIf();
//addExprElse();
addExprElse();
}
private static class PyKeywordCompletionProvider extends CompletionProvider<CompletionParameters> {
@@ -0,0 +1,23 @@
package com.jetbrains.python.codeInsight;
import com.intellij.psi.PsiReferenceContributor;
import com.intellij.psi.PsiReferenceRegistrar;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.PyAssignmentStatement;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import com.jetbrains.python.psi.PyTargetExpression;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author yole
*/
public class PyStdReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(psiElement(PyStringLiteralExpression.class).inside(
psiElement(PyAssignmentStatement.class).withFirstChild(
psiElement(PyTargetExpression.class).withName(PyNames.ALL))),
new PyDunderAllReferenceProvider());
}
}
@@ -0,0 +1,55 @@
package com.jetbrains.python.codeInsight;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author yole
*/
public class PySuperMethodCompletionContributor extends CompletionContributor {
public PySuperMethodCompletionContributor() {
extend(CompletionType.BASIC,
psiElement().afterLeafSkipping(psiElement().whitespace(), psiElement().withElementType(PyTokenTypes.DEF_KEYWORD)),
new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
PsiElement position = parameters.getOriginalPosition();
PyClass containingClass = PsiTreeUtil.getParentOfType(position, PyClass.class);
if (containingClass == null && position instanceof PsiWhiteSpace) {
position = PsiTreeUtil.prevLeaf(position);
containingClass = PsiTreeUtil.getParentOfType(position, PyClass.class);
}
if (containingClass == null) {
return;
}
List<String> seenNames = new ArrayList<String>();
for (PyFunction function : containingClass.getMethods()) {
seenNames.add(function.getName());
}
for (PyClass ancestor : containingClass.iterateAncestors()) {
for (PyFunction superMethod : ancestor.getMethods()) {
if (!seenNames.contains(superMethod.getName())) {
result.addElement(LookupElementBuilder.create(superMethod.getName() + superMethod.getParameterList().getText() + ":"));
seenNames.add(superMethod.getName());
}
}
}
}
});
}
}
@@ -39,7 +39,14 @@ public class PythonFindUsagesProvider implements FindUsagesProvider {
return "function";
}
if (element instanceof PyClass) return "class";
if (element instanceof PyReferenceExpression || element instanceof PyTargetExpression) return "variable";
if (element instanceof PyReferenceExpression) return "variable";
if (element instanceof PyTargetExpression) {
final PyImportElement importElement = PsiTreeUtil.getParentOfType(element, PyImportElement.class);
if (importElement != null && importElement.getAsNameElement() == element) {
return "imported module alias";
}
return "variable";
}
return "";
}
@@ -1,7 +1,13 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface PyAnnotation extends PyElement {
PyExpression getValue();
@Nullable
PyClass resolveToClass();
}
@@ -73,4 +73,7 @@ extends
*/
@Nullable
Property getProperty();
@Nullable
PyAnnotation getAnnotation();
}
@@ -5,6 +5,7 @@ import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyNamedParameterStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a named parameter, as opposed to a tuple parameter.
@@ -20,5 +21,8 @@ public interface PyNamedParameter extends PyParameter, PsiNamedElement, PsiNameI
*/
@NotNull
String getRepr(boolean includeDefaultValue);
@Nullable
PyAnnotation getAnnotation();
}
@@ -1,7 +1,12 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.jetbrains.python.psi.PyAnnotation;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
/**
* @author yole
@@ -10,4 +15,22 @@ public class PyAnnotationImpl extends PyElementImpl implements PyAnnotation {
public PyAnnotationImpl(ASTNode astNode) {
super(astNode);
}
@Override
public PyExpression getValue() {
return findChildByClass(PyExpression.class);
}
@Override
public PyClass resolveToClass() {
PyExpression expr = getValue();
if (expr instanceof PyReferenceExpression) {
final PsiPolyVariantReference reference = ((PyReferenceExpression)expr).getReference();
final PsiElement result = reference.resolve();
if (result instanceof PyClass) {
return (PyClass) result;
}
}
return null;
}
}
@@ -198,7 +198,11 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
public PyCallExpression createCallExpression(String functionName) {
final PsiFile dummyFile = createDummyFile(LanguageLevel.getDefault(), functionName + "()");
return (PyCallExpression)dummyFile.getFirstChild().getFirstChild();
final PsiElement element = dummyFile.getFirstChild().getFirstChild();
if (!(element instanceof PyCallExpression)) {
throw new IllegalArgumentException("Invalid call expression text " + functionName);
}
return (PyCallExpression)element;
}
public PyImportStatement createImportStatementFromText(final String text) {
@@ -118,6 +118,14 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
@Nullable
public PyType getReturnType(TypeEvalContext typeEvalContext, @Nullable PyReferenceExpression callSite) {
PyAnnotation anno = getAnnotation();
if (anno != null) {
PyClass pyClass = anno.resolveToClass();
if (pyClass != null) {
return new PyClassType(pyClass, false);
}
}
for(PyTypeProvider typeProvider: Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
final PyType returnType = typeProvider.getReturnType(this, callSite, typeEvalContext);
if (returnType != null) {
@@ -382,4 +390,9 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
}
return null;
}
@Override
public PyAnnotation getAnnotation() {
return findChildByClass(PyAnnotation.class);
}
}
@@ -3,6 +3,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
@@ -120,6 +121,11 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl<PyNamedParame
return sb.toString();
}
@Override
public PyAnnotation getAnnotation() {
return findChildByClass(PyAnnotation.class);
}
public Icon getIcon(final int flags) {
return Icons.PARAMETER_ICON;
}
@@ -152,6 +158,13 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl<PyNamedParame
if (isPositionalContainer()) {
return PyBuiltinCache.getInstance(this).getTupleType();
}
PyAnnotation anno = getAnnotation();
if (anno != null) {
final PyClass pyClass = anno.resolveToClass();
if (pyClass != null) {
return new PyClassType(pyClass, false);
}
}
for(PyTypeProvider provider: Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
PyType result = provider.getParameterType(this, func, context);
if (result != null) return result;
@@ -2,6 +2,9 @@ package com.jetbrains.python.psi.impl;
import com.intellij.psi.PsiElementResolveResult;
import com.intellij.psi.ResolveResult;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.psi.PyImportElement;
import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import org.jetbrains.annotations.NotNull;
@@ -24,4 +27,15 @@ public class PyTargetReference extends PyReferenceImpl {
// resolve to self if no other target found
return new ResolveResult[] { new PsiElementResolveResult(myElement) };
}
@NotNull
@Override
public Object[] getVariants() {
final PyImportElement importElement = PsiTreeUtil.getParentOfType(myElement, PyImportElement.class);
// reference completion is useless in 'as' part of import statement (PY-2384)
if (importElement != null && myElement == importElement.getAsNameElement()) {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
return super.getVariants();
}
}
@@ -36,7 +36,7 @@ public class VariantsProcessor implements PsiScopeProcessor {
myContext = context;
}
public VariantsProcessor(PsiElement context, final Condition<PsiElement> nodeFilter, final Condition<String> nameFilter) {
public VariantsProcessor(PsiElement context, @Nullable final Condition<PsiElement> nodeFilter, @Nullable final Condition<String> nameFilter) {
myContext = context;
myNodeFilter = nodeFilter;
myNameFilter = nameFilter;
@@ -60,6 +60,7 @@ public class VariantsProcessor implements PsiScopeProcessor {
if (item.getObject() instanceof PyFunction && ((PyFunction) item.getObject()).getProperty() == null &&
!isSingleArgDecoratorCall(myContext, (PyFunction)item.getObject())) {
item = item.setInsertHandler(PyFunctionInsertHandler.INSTANCE);
item = item.setTailText(((PyFunction) item.getObject()).getParameterList().getText());
}
else if (item.getObject() instanceof PyClass) {
item = item.setInsertHandler(PyClassInsertHandler.INSTANCE);
@@ -74,7 +74,7 @@ public abstract class PythonCommandLineState extends CommandLineState {
}
public ExecutionResult execute(Executor executor, CommandLinePatcher... patchers) throws ExecutionException {
final ColoredProcessHandler processHandler = startProcess(patchers);
final ProcessHandler processHandler = startProcess(patchers);
final ConsoleView console = createAndAttachConsole(getConfig().getProject(), processHandler, executor);
List<AnAction> actions = Lists.newArrayList(createActions(console, processHandler));
@@ -104,7 +104,7 @@ public abstract class PythonCommandLineState extends CommandLineState {
}
}
protected ColoredProcessHandler startProcess() throws ExecutionException {
protected ProcessHandler startProcess() throws ExecutionException {
return startProcess(null);
}
@@ -115,10 +115,10 @@ public abstract class PythonCommandLineState extends CommandLineState {
* @return handler of the started process
* @throws ExecutionException
*/
protected ColoredProcessHandler startProcess(CommandLinePatcher... patchers) throws ExecutionException {
protected ProcessHandler startProcess(CommandLinePatcher... patchers) throws ExecutionException {
GeneralCommandLine commandLine = generateCommandLine(patchers);
final ColoredProcessHandler processHandler = doCreateProcess(commandLine);
final ProcessHandler processHandler = doCreateProcess(commandLine);
ProcessTerminatedListener.attach(processHandler);
return processHandler;
}
@@ -133,7 +133,7 @@ public abstract class PythonCommandLineState extends CommandLineState {
return commandLine;
}
protected ColoredProcessHandler doCreateProcess(GeneralCommandLine commandLine) throws ExecutionException {
protected ProcessHandler doCreateProcess(GeneralCommandLine commandLine) throws ExecutionException {
return PythonProcessHandler.createProcessHandler(commandLine);
}
@@ -4,6 +4,7 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ColoredProcessHandler;
import com.intellij.execution.process.RunnerMediator;
import com.intellij.execution.process.UnixProcessManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;
@@ -12,17 +13,14 @@ import org.jetbrains.annotations.NotNull;
* @author traff
*/
public class PythonProcessHandler extends ColoredProcessHandler {
private final String myProcessUid;
private PythonProcessHandler(@NotNull Process process, @NotNull GeneralCommandLine commandLine, @NotNull String processUid) {
private PythonProcessHandler(@NotNull Process process, @NotNull GeneralCommandLine commandLine) {
super(process, commandLine.getCommandLineString());
myProcessUid = processUid;
}
@Override
protected void destroyProcessImpl() {
super.destroyProcessImpl();
if (RunnerMediator.canSendSignals()) {
if (RunnerMediator.isUnix()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
long millis = System.currentTimeMillis();
@@ -35,7 +33,7 @@ public class PythonProcessHandler extends ColoredProcessHandler {
if (System.currentTimeMillis() - millis > 5000L) {
if (Messages.showYesNoDialog("Do you want to terminate the process?", "Process is not responding", null) == 0) {
RunnerMediator.sendSigKill(getProcess());
UnixProcessManager.sendSigKillToProcessTree(getProcess());
return;
}
else {
@@ -60,10 +58,8 @@ public class PythonProcessHandler extends ColoredProcessHandler {
public static PythonProcessHandler createProcessHandler(GeneralCommandLine commandLine)
throws ExecutionException {
String processUid = RunnerMediator.injectUid(commandLine);
Process p = commandLine.createProcess();
return new PythonProcessHandler(p, commandLine, processUid);
return new PythonProcessHandler(p, commandLine);
}
}
@@ -0,0 +1 @@
a = 1 if True else <caret>
@@ -0,0 +1 @@
a = 1 if True el<caret>
@@ -0,0 +1,6 @@
class Foo:
def xyzzy(self, *args, **kwargs):
pass
class Bar(Foo):
def xyzzy(self, *args, **kwargs):
@@ -0,0 +1,6 @@
class Foo:
def xyzzy(self, *args, **kwargs):
pass
class Bar(Foo):
def xy<caret>
@@ -0,0 +1,3 @@
__all__ = ['foo']
def f<caret>oo(): pass
@@ -0,0 +1,3 @@
__all__ = ['bar']
def bar(): pass
@@ -131,6 +131,29 @@ public class PyTypeTest extends PyLightFixtureTestCase {
assertEquals("ImportError", type.getName());
}
public void testTypeAnno() {
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON30);
try {
PyClassType type = (PyClassType) doTest("def foo(x: str) -> list: expr = x");
assertEquals("str", type.getName());
}
finally {
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
}
}
public void testReturnTypeAnno() {
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON30);
try {
PyClassType type = (PyClassType) doTest("def foo(x) -> list: return x\n" +
"expr = foo(None)");
assertEquals("list", type.getName());
}
finally {
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
}
}
private PyType doTest(final String text) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
@@ -239,7 +239,12 @@ public class PythonCompletionTest extends PyLightFixtureTestCase {
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
}
}
public void testSuperMethod() { // PY-170
doTest();
}
public void testElseInCondExpr() { // PY-2397
doTest();
}
}
@@ -49,6 +49,10 @@ public class PyRenameTest extends PyLightFixtureTestCase {
doTest("bar");
}
public void testUpdateAll() { // PY-986
doTest("bar");
}
private void doTest(final String newName) {
myFixture.configureByFile("refactoring/rename/" + getTestName(true) + ".py");
myFixture.renameElementAtCaret(newName);