Merge remote branch 'origin/master'

This commit is contained in:
Dmitry Cheryasov
2011-07-06 17:07:31 +03:00
28 changed files with 430 additions and 92 deletions
@@ -26,7 +26,7 @@ public class PythonModuleType extends PythonModuleTypeBase<PythonModuleBuilder>
final PythonModuleBuilder moduleBuilder,
final ModulesProvider modulesProvider) {
ArrayList<ModuleWizardStep> steps = new ArrayList<ModuleWizardStep>();
steps.add(new PythonSdkSelectStep(moduleBuilder, null, null, wizardContext.getProject()));
steps.add(new PythonSdkSelectStep(moduleBuilder, null, "reference.project.structure.sdk.python", wizardContext.getProject()));
final List<FrameworkSupportProvider> frameworkSupportProviderList = FrameworkSupportUtil.getProviders(getInstance());
if (!frameworkSupportProviderList.isEmpty()) {
steps.add(new SupportForFrameworksStep(moduleBuilder, LibrariesContainerFactory.createContainer(wizardContext.getProject())));
@@ -7,10 +7,14 @@ import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.python.psi.PyFileElementType;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -49,25 +53,10 @@ public class PythonFoldingBuilder implements FoldingBuilder, DumbAware {
}
}
else if (node.getElementType() == PyElementTypes.STATEMENT_LIST) {
IElementType elType = node.getTreeParent().getElementType();
if (elType == PyElementTypes.FUNCTION_DECLARATION || elType == PyElementTypes.CLASS_DECLARATION) {
ASTNode colon = node.getTreeParent().findChildByType(PyTokenTypes.COLON);
if (colon != null && colon.getStartOffset() + 1 < node.getTextRange().getEndOffset() - 1) {
final CharSequence chars = node.getChars();
int nodeStart = node.getTextRange().getStartOffset();
int endOffset = node.getTextRange().getEndOffset();
while(endOffset > colon.getStartOffset()+2 && endOffset > nodeStart && Character.isWhitespace(chars.charAt(endOffset - nodeStart - 1))) {
endOffset--;
}
descriptors.add(new FoldingDescriptor(node, new TextRange(colon.getStartOffset() + 1, endOffset)));
}
else {
TextRange range = node.getTextRange();
if (range.getStartOffset() < range.getEndOffset() - 1) { // only for ranges at least 1 char wide
descriptors.add(new FoldingDescriptor(node, range));
}
}
}
foldStatementList(node, descriptors);
}
else if (node.getElementType() == PyElementTypes.STRING_LITERAL_EXPRESSION) {
foldDocString(node, descriptors);
}
ASTNode child = node.getFirstChildNode();
@@ -77,6 +66,53 @@ public class PythonFoldingBuilder implements FoldingBuilder, DumbAware {
}
}
private static void foldStatementList(ASTNode node, List<FoldingDescriptor> descriptors) {
IElementType elType = node.getTreeParent().getElementType();
if (elType == PyElementTypes.FUNCTION_DECLARATION || elType == PyElementTypes.CLASS_DECLARATION) {
ASTNode colon = node.getTreeParent().findChildByType(PyTokenTypes.COLON);
if (colon != null && colon.getStartOffset() + 1 < node.getTextRange().getEndOffset() - 1) {
final CharSequence chars = node.getChars();
int nodeStart = node.getTextRange().getStartOffset();
int endOffset = node.getTextRange().getEndOffset();
while(endOffset > colon.getStartOffset()+2 && endOffset > nodeStart && Character.isWhitespace(chars.charAt(endOffset - nodeStart - 1))) {
endOffset--;
}
descriptors.add(new FoldingDescriptor(node, new TextRange(colon.getStartOffset() + 1, endOffset)));
}
else {
TextRange range = node.getTextRange();
if (range.getStartOffset() < range.getEndOffset() - 1) { // only for ranges at least 1 char wide
descriptors.add(new FoldingDescriptor(node, range));
}
}
}
}
private static void foldDocString(ASTNode node, List<FoldingDescriptor> descriptors) {
if (getDocStringOwnerType(node) != null && StringUtil.countChars(node.getText(), '\n') > 1) {
descriptors.add(new FoldingDescriptor(node, node.getTextRange()));
}
}
@Nullable
private static IElementType getDocStringOwnerType(ASTNode node) {
final ASTNode treeParent = node.getTreeParent();
IElementType parentType = treeParent.getElementType();
if (parentType == PyElementTypes.EXPRESSION_STATEMENT && treeParent.getTreeParent() != null) {
final ASTNode parent2 = treeParent.getTreeParent();
if (parent2.getElementType() == PyElementTypes.STATEMENT_LIST && parent2.getTreeParent() != null && treeParent == parent2.getFirstChildNode()) {
final ASTNode parent3 = parent2.getTreeParent();
if (parent3.getElementType() == PyElementTypes.FUNCTION_DECLARATION || parent3.getElementType() == PyElementTypes.CLASS_DECLARATION) {
return parent3.getElementType();
}
}
else if (parent2.getElementType() instanceof PyFileElementType) {
return parent2.getElementType();
}
}
return null;
}
private static boolean isImport(ASTNode node, boolean orWhitespace) {
if (node == null) return false;
IElementType elementType = node.getElementType();
@@ -90,6 +126,14 @@ public class PythonFoldingBuilder implements FoldingBuilder, DumbAware {
if (isImport(node, false)) {
return "import ...";
}
if (node.getElementType() == PyElementTypes.STRING_LITERAL_EXPRESSION) {
final String stringValue = ((PyStringLiteralExpression)node.getPsi()).getStringValue().trim();
final String[] lines = LineTokenizer.tokenize(stringValue, true);
if (lines.length > 2 && lines[1].trim().length() == 0) {
return "\"\"\"" + lines [0].trim() + "...\"\"\"";
}
return "\"\"\"...\"\"\"";
}
return "...";
}
@@ -97,6 +141,16 @@ public class PythonFoldingBuilder implements FoldingBuilder, DumbAware {
if (isImport(node, false)) {
return CodeFoldingSettings.getInstance().COLLAPSE_IMPORTS;
}
if (node.getElementType() == PyElementTypes.STRING_LITERAL_EXPRESSION) {
if (getDocStringOwnerType(node) == PyElementTypes.FUNCTION_DECLARATION && CodeFoldingSettings.getInstance().COLLAPSE_METHODS) {
// method will be collapsed, no need to also collapse docstring
return false;
}
return CodeFoldingSettings.getInstance().COLLAPSE_DOC_COMMENTS;
}
if (node.getElementType() == PyElementTypes.STATEMENT_LIST && node.getTreeParent().getElementType() == PyElementTypes.FUNCTION_DECLARATION) {
return CodeFoldingSettings.getInstance().COLLAPSE_METHODS;
}
return false;
}
}
@@ -109,6 +109,10 @@ public class BuildoutFacetConfiguration implements FacetConfiguration {
@Override
public void disposeUIResources() { }
}
@Override
public String getHelpTopic() {
return "reference-python-buildout";
}
}
}
@@ -53,7 +53,8 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
@Override public boolean matches(char c) {
return Character.isLetterOrDigit(c) || c == '_';
}}.negate();
if (docString.substring(tagRange.getStartOffset(), tagRange.getEndOffset()).startsWith(":")) {
final String tagName = docString.substring(tagRange.getStartOffset(), tagRange.getEndOffset());
if (tagName.startsWith(":")) {
int ws = CharMatcher.anyOf(" \t*").indexIn(docString, pos+1);
if (ws != -1) {
int next = CharMatcher.anyOf(" \t*").negate().indexIn(docString, ws);
@@ -69,10 +70,9 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
if (endPos < 0) {
endPos = docString.length();
}
result.add(new DocStringParameterReference(element, new TextRange(pos, endPos)));
if (docString.substring(tagRange.getStartOffset(), tagRange.getEndOffset()).equals(":type") ||
docString.substring(tagRange.getStartOffset(), tagRange.getEndOffset()).equals(":rtype")) {
result.add(new DocStringParameterReference(element, new TextRange(pos, endPos)));
if (tagName.equals(":type") || tagName.equals(":rtype") || tagName.equals("@type") || tagName.equals("@rtype")) {
pos = CharMatcher.anyOf(" \t*").negate().indexIn(docString, endPos+1);
endPos = CharMatcher.anyOf("\n\r").indexIn(docString, pos+1);
if (endPos == -1)
@@ -85,7 +85,7 @@ public class SphinxDocString extends StructuredDocString {
String tagValue = line.substring(tagEnd).trim();
tagValue = StringUtil.replace(tagValue, ":py:class:", "");
tagValue = StringUtil.replace(tagValue, ":class:", "");
tagValue = tagValue.replaceAll("`(\\w+)`", "$1");
tagValue = tagValue.replaceAll("`([^`]+)`", "$1");
int pos = tagValue.indexOf(':');
if (pos < 0) return index;
String value = tagValue.substring(pos+1).trim();
@@ -23,7 +23,7 @@ public abstract class StructuredDocString {
if (text == null) {
return null;
}
if (text.contains(":param ") || text.contains(":rtype") || text.contains(":type ")) {
if (text.contains(":param ") || text.contains(":rtype") || text.contains(":type")) {
return new SphinxDocString(text);
}
return new EpydocString(text);
@@ -177,7 +177,7 @@ public class PyBlock implements ASTBlock {
childIndent = Indent.getNormalIndent();
}
}
else if (parentType == PyElementTypes.PARENTHESIZED_EXPRESSION) {
else if (parentType == PyElementTypes.PARENTHESIZED_EXPRESSION && hasLineBreaksBefore(child, 1)) {
childIndent = Indent.getNormalIndent();
}
@@ -230,6 +230,9 @@ public class PyBlock implements ASTBlock {
PyArgumentList argList = (PyArgumentList) _node.getPsi();
return argList != null && argList.getArguments().length > 1;
}
if (child.getElementType() == PyTokenTypes.COMMA) {
return false;
}
return true;
}
@@ -242,7 +245,8 @@ public class PyBlock implements ASTBlock {
}
private static boolean hasLineBreaksBefore(ASTNode child, int minCount) {
return isWhitespaceWithLineBreaks(TreeUtil.findLastLeaf(child.getTreePrev()), minCount) ||
final ASTNode treePrev = child.getTreePrev();
return (treePrev != null && isWhitespaceWithLineBreaks(TreeUtil.findLastLeaf(treePrev), minCount)) ||
isWhitespaceWithLineBreaks(child.getFirstChildNode(), minCount);
}
@@ -1,12 +1,15 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.stubs.DefaultStubBuilder;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyIfStatement;
import com.jetbrains.python.psi.PyUtil;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
@@ -23,9 +26,17 @@ public class PyFileStubBuilder extends DefaultStubBuilder {
@Override
protected boolean skipChildProcessingWhenBuildingStubs(PsiElement element, PsiElement child) {
if (element instanceof PyIfStatement) {
return PyUtil.isIfNameEqualsMain((PyIfStatement)element);
return element instanceof PyIfStatement && PyUtil.isIfNameEqualsMain((PyIfStatement)element);
}
@Override
public boolean skipChildProcessingWhenBuildingStubs(@Nullable ASTNode parent, IElementType childType) {
if (parent != null) {
final PsiElement psi = parent.getPsi();
if (psi != null) {
return psi instanceof PyIfStatement && PyUtil.isIfNameEqualsMain((PyIfStatement)psi);
}
}
return false;
return super.skipChildProcessingWhenBuildingStubs(parent, childType);
}
}
@@ -460,7 +460,12 @@ public class PyExtractMethodUtil {
}
};
final AbstractExtractMethodDialog dialog = new AbstractExtractMethodDialog(project, "method_name", fragment, validator, decorator);
final AbstractExtractMethodDialog dialog = new AbstractExtractMethodDialog(project, "method_name", fragment, validator, decorator) {
@Override
protected String getHelpId() {
return "python.reference.extractMethod";
}
};
dialog.show();
//return if don`t want to extract method
@@ -4,10 +4,10 @@ import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.util.text.StringUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* @author yole
@@ -20,7 +20,7 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor {
@Override
public Collection<String> suggestHomePaths() {
List<String> result = new ArrayList<String>();
Set<String> result = new TreeSet<String>();
String root = System.getenv("ProgramFiles(x86)");
if (root == null) {
root = System.getenv("ProgramFiles");
@@ -36,6 +36,8 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor {
}
}
}
WinPythonSdkFlavor.findInPath(result, "ipy.exe");
WinPythonSdkFlavor.findInPath(result, "ipy64.exe");
return result;
}
@@ -104,7 +104,7 @@ public abstract class PythonSdkFlavor {
}
public void initPythonPath(GeneralCommandLine cmd, Collection<String> path) {
addToEnv(cmd, PYTHONPATH, StringUtil.join(path, File.pathSeparator));
addToEnv(cmd, PYTHONPATH, appendSystemPythonPath(StringUtil.join(path, File.pathSeparator)));
}
public static void addToEnv(GeneralCommandLine cmd, final String key, String value) {
@@ -0,0 +1,47 @@
package com.jetbrains.python.structureView;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.treeView.smartTree.ActionPresentation;
import com.intellij.ide.util.treeView.smartTree.ActionPresentationData;
import com.intellij.ide.util.treeView.smartTree.Filter;
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
/**
* @author vlan
*/
public class PyFieldsFilter implements Filter {
private static final String ID = "SHOW_FIELDS";
@Override
public boolean isReverted() {
return true;
}
@Override
public boolean isVisible(TreeElement treeNode) {
if (treeNode instanceof PyStructureViewElement) {
final PyStructureViewElement sve = (PyStructureViewElement)treeNode;
return !sve.isField();
}
return true;
}
@NotNull
@Override
public String getName() {
return ID;
}
@Override
public String toString() {
return getName();
}
@NotNull
@Override
public ActionPresentation getPresentation() {
return new ActionPresentationData(IdeBundle.message("action.structureview.show.fields"), null, PlatformIcons.FIELD_ICON);
}
}
@@ -0,0 +1,50 @@
package com.jetbrains.python.structureView;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.treeView.smartTree.ActionPresentation;
import com.intellij.ide.util.treeView.smartTree.ActionPresentationData;
import com.intellij.ide.util.treeView.smartTree.Filter;
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.openapi.util.IconLoader;
import com.jetbrains.python.psi.PyElement;
import org.jetbrains.annotations.NotNull;
/**
* @author vlan
*/
public class PyInheritedMembersFilter implements Filter {
private static final String ID = "SHOW_INHERITED";
@Override
public boolean isReverted() {
return true;
}
@Override
public boolean isVisible(TreeElement treeNode) {
if (treeNode instanceof PyStructureViewElement) {
final PyStructureViewElement sve = (PyStructureViewElement)treeNode;
return !sve.isInherited();
}
return true;
}
@NotNull
@Override
public String getName() {
return ID;
}
@Override
public String toString() {
return getName();
}
@NotNull
@Override
public ActionPresentation getPresentation() {
return new ActionPresentationData(IdeBundle.message("action.structureview.show.inherited"),
null,
IconLoader.getIcon("/hierarchy/supertypes.png"));
}
}
@@ -2,18 +2,17 @@ package com.jetbrains.python.structureView;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.LayeredIcon;
import com.intellij.util.Function;
import com.intellij.util.PlatformIcons;
import com.jetbrains.python.PyIcons;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.ParamHelper;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -32,26 +31,39 @@ public class PyStructureViewElement implements StructureViewTreeElement {
NORMAL, // visible
INVISIBLE, // not visible: e.g. local to function
PRIVATE, // "__foo" in a class
PROTECTED, // "_foo"
PREDEFINED // like "__init__"; only if really visible
}
private PyElement myElement;
private Visibility myVisibility;
private Icon myIcon;
private boolean myInherited;
private boolean myField;
public PyStructureViewElement(PyElement element, Visibility vis) {
public PyStructureViewElement(PyElement element, Visibility vis, boolean inherited, boolean field) {
myElement = element;
myVisibility = vis;
myInherited = inherited;
myField = field;
}
public PyStructureViewElement(PyElement element) {
this(element, Visibility.NORMAL);
this(element, Visibility.NORMAL, false, false);
}
public PyElement getValue() {
return myElement;
}
public boolean isInherited() {
return myInherited;
}
public boolean isField() {
return myField;
}
public void navigate(boolean requestFocus) {
myElement.navigate(requestFocus);
}
@@ -68,46 +80,69 @@ public class PyStructureViewElement implements StructureViewTreeElement {
myIcon = icon;
}
@Override
public boolean equals(Object o) {
if (o instanceof StructureViewTreeElement) {
final Object value = ((StructureViewTreeElement)o).getValue();
final String name = myElement.getName();
if (value instanceof PyElement && name != null) {
return name.equals(((PyElement)value).getName());
}
}
return false;
}
@Override
public int hashCode() {
final String name = myElement.getName();
return name != null ? name.hashCode() : 0;
}
public StructureViewTreeElement[] getChildren() {
final Set<PyElement> childrenElements = new LinkedHashSet<PyElement>();
myElement.acceptChildren(new PyElementVisitor() {
@Override
public void visitElement(PsiElement element) {
if (element instanceof PyClass || element instanceof PyFunction ||
(!(myElement instanceof PyClass) && isWorthyItem(element))) {
childrenElements.add((PyElement)element);
}
else {
element.acceptChildren(this);
}
}
});
final Collection<StructureViewTreeElement> children = new ArrayList<StructureViewTreeElement>();
for (PyElement element : childrenElements) {
final Visibility vis;
if (PsiTreeUtil.getParentOfType(element, PyFunction.class) != null) {
// whatever is defined inside a def, is hidden
vis = Visibility.INVISIBLE;
}
else {
vis = getVisibilityByName(element.getName());
}
final PyStructureViewElement e = new PyStructureViewElement(element, vis);
children.add(e);
if (element instanceof PyClass && element.isValid()) {
PyClass the_exception = PyBuiltinCache.getInstance(element).getClass("Exception");
final PyClass cls = (PyClass)element;
for (PyClass anc : cls.iterateAncestorClasses()) {
if (anc == the_exception) {
e.setIcon(PlatformIcons.EXCEPTION_CLASS_ICON);
break;
}
final Collection<StructureViewTreeElement> children = new LinkedHashSet<StructureViewTreeElement>();
for (PyElement e : getElementChildren(myElement)) {
children.add(new PyStructureViewElement(e, getElementVisibility(e), false, elementIsField(e)));
}
if (myElement instanceof PyClass) {
for (PyClass c : ((PyClass)myElement).iterateAncestorClasses()) {
for (PyElement e: getElementChildren(c)) {
children.add(new PyStructureViewElement(e, getElementVisibility(e), true, elementIsField(e)));
}
}
}
return children.toArray(new StructureViewTreeElement[children.size()]);
}
private static boolean elementIsField(PyElement element) {
return element instanceof PyTargetExpression && PsiTreeUtil.getParentOfType(element, PyClass.class) != null;
}
private static Visibility getElementVisibility(PyElement element) {
if (!(element instanceof PyTargetExpression) && PsiTreeUtil.getParentOfType(element, PyFunction.class) != null) {
return Visibility.INVISIBLE;
}
else {
return getVisibilityByName(element.getName());
}
}
private static Collection<PyElement> getElementChildren(final PyElement element) {
final Collection<PyElement> children = new ArrayList<PyElement>();
element.acceptChildren(new PyElementVisitor() {
@Override
public void visitElement(PsiElement e) {
if (e instanceof PyClass || e instanceof PyFunction ||
(!(element instanceof PyClass) && isWorthyItem(e))) {
children.add((PyElement)e);
}
else {
e.acceptChildren(this);
}
}
});
final Collection<PyTargetExpression> attrs = new ArrayList<PyTargetExpression>();
if (myElement instanceof PyClass) {
final PyClass c = (PyClass)myElement;
if (element instanceof PyClass) {
final PyClass c = (PyClass)element;
final Comparator<PyTargetExpression> comparator = new Comparator<PyTargetExpression>() {
@Override
public int compare(PyTargetExpression e1, PyTargetExpression e2) {
@@ -125,19 +160,24 @@ public class PyStructureViewElement implements StructureViewTreeElement {
}
for (PyTargetExpression e : attrs) {
if (e.isValid()) {
children.add(new PyStructureViewElement(e, getVisibilityByName(e.getName())));
children.add(e);
}
}
return children.toArray(new StructureViewTreeElement[children.size()]);
return children;
}
private static Visibility getVisibilityByName(@Nullable String name) {
if (name != null && name.startsWith("__")) {
if (PyNames.UnderscoredAttributes.contains(name)) {
return Visibility.PREDEFINED;
if (name != null) {
if (name.startsWith("__")) {
if (PyNames.UnderscoredAttributes.contains(name)) {
return Visibility.PREDEFINED;
}
else {
return Visibility.PRIVATE;
}
}
else {
return Visibility.PRIVATE;
else if (name.startsWith("_")) {
return Visibility.PROTECTED;
}
}
return Visibility.NORMAL;
@@ -193,6 +233,9 @@ public class PyStructureViewElement implements StructureViewTreeElement {
@Nullable
public TextAttributesKey getTextAttributesKey() {
if (isInherited()) {
return CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES;
}
return null;
}
@@ -211,13 +254,15 @@ public class PyStructureViewElement implements StructureViewTreeElement {
LayeredIcon icon = new LayeredIcon(2);
icon.setIcon(normal_icon, 0);
Icon overlay = null;
if (myVisibility == Visibility.PRIVATE) {
if (myVisibility == Visibility.PRIVATE || myVisibility == Visibility.PROTECTED) {
overlay = PyIcons.PRIVATE;
}
else if (myVisibility == Visibility.PREDEFINED) {
overlay = PyIcons.PREDEFINED;
}
else if (myVisibility == Visibility.INVISIBLE) overlay = PyIcons.INVISIBLE;
else if (myVisibility == Visibility.INVISIBLE) {
overlay = PyIcons.INVISIBLE;
}
if (overlay != null) {
icon.setIcon(overlay, 1);
}
@@ -3,6 +3,7 @@ package com.jetbrains.python.structureView;
import com.intellij.ide.structureView.StructureViewModel;
import com.intellij.ide.structureView.StructureViewModelBase;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.util.treeView.smartTree.Filter;
import com.intellij.ide.util.treeView.smartTree.Sorter;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.psi.*;
@@ -34,6 +35,15 @@ public class PyStructureViewModel extends StructureViewModelBase implements Stru
return element instanceof PyClass;
}
@NotNull
@Override
public Filter[] getFilters() {
return new Filter[] {
new PyInheritedMembersFilter(),
new PyFieldsFilter(),
};
}
@Override
public boolean isAutoExpand(StructureViewTreeElement element) {
return element.getValue() instanceof PsiFile;
+7
View File
@@ -0,0 +1,7 @@
def foo():<fold text='...'>
<fold text='"""This is a docstring...."""'>"""
This is a docstring.
It spans several lines.
"""</fold>:
pass</fold>
@@ -0,0 +1,8 @@
def bad_autoformat_example():
a = 5
b = 10
print a, b
(a, b) = b, a
print a, b
a, b = b, a
print a, b
@@ -0,0 +1,8 @@
def bad_autoformat_example():
a = 5
b = 10
print a, b
(a, b) = b, a
print a, b
a, b = b, a
print a, b
@@ -0,0 +1,9 @@
class <caret>Xyzzy:
pass
def foo(p):
"""
@param p: the magic word
@type p: Xyzzy
@return:
"""
@@ -0,0 +1,9 @@
class Shazam:
pass
def foo(p):
"""
@param p: the magic word
@type p: Shazam
@return:
"""
@@ -0,0 +1,6 @@
class C(object):
def f(self, x):
self.x = x
def __str__(self):
return self.x
+1
View File
@@ -1,2 +1,3 @@
if __name__ == '__main__':
import sys
xyzzy = None
@@ -13,4 +13,8 @@ public class PyFoldingTest extends PyLightFixtureTestCase {
public void testClassTrailingSpace() { // PY-2544
doTest();
}
public void testDocString() {
doTest();
}
}
@@ -113,6 +113,10 @@ public class PyFormatterTest extends PyLightFixtureTestCase {
doTest();
}
public void testTupleAssignment() { // PY-4034 comment
doTest();
}
public void testPsiFormatting() { // IDEA-69724
String initial =
"def method_name(\n" +
@@ -271,6 +271,20 @@ public class PyIndentTest extends PyLightFixtureTestCase {
"");
}
public void testNestedLists() { // PY-4034
doTest("mat = [\n" +
" [1, 2, 3, 4, 4.5],\n" +
" [5, 6, 7, 8],\n" +
" [9, 10, 11, 12],<caret>\n" +
"]",
"mat = [\n" +
" [1, 2, 3, 4, 4.5],\n" +
" [5, 6, 7, 8],\n" +
" [9, 10, 11, 12],\n" +
" <caret>\n" +
"]");
}
/*
TODO: formatter core problem?
public void testAlignListBeforeEquals() throws Exception {
@@ -24,10 +24,12 @@ public class PyStructureViewTest extends PyLightFixtureTestCase {
" D1(C)\n" +
" D2(C)\n" +
" D3(lib1.C)\n" +
" D4(foo.bar.C)\n");
" D4(foo.bar.C)\n",
false);
}
public void testAttributes() { // PY-3371
// PY-3371
public void testAttributes() {
myFixture.configureByFile(TEST_DIRECTORY + "attributes.py");
doTest("-attributes.py\n" +
" -B(object)\n" +
@@ -48,13 +50,38 @@ public class PyStructureViewTest extends PyLightFixtureTestCase {
" i3\n" +
" i4\n" +
" i5\n" +
" g2\n");
" g2\n",
false);
}
private void doTest(final String expected) {
// PY-3936
public void testInherited() {
myFixture.configureByFile(TEST_DIRECTORY + "inherited.py");
doTest("-inherited.py\n" +
" -C(object)\n" +
" f(self, x)\n" +
" __str__(self)\n" +
" x\n" +
" __delattr__(self, name)\n" +
" __getattribute__(self, name)\n" +
" __hash__(self)\n" +
" __init__(self)\n" +
" __new__(cls, *more)\n" +
" __reduce_ex__(self, *args, **kwargs)\n" +
" __reduce__(self, *args, **kwargs)\n" +
" __repr__(self)\n" +
" __setattr__(self, name, value)\n" +
" __class__\n" +
" __dict__\n" +
" __doc__\n",
true);
}
private void doTest(final String expected, final boolean inherited) {
myFixture.testStructureView(new Consumer<StructureViewComponent>() {
@Override
public void consume(StructureViewComponent component) {
component.setActionActive("SHOW_INHERITED", !inherited);
assertTreeEqual(component.getTree(), expected);
}
});
@@ -1,6 +1,3 @@
/*
* @author max
*/
package com.jetbrains.python;
import com.intellij.openapi.application.Result;
@@ -26,6 +23,10 @@ import com.jetbrains.python.toolbox.Maybe;
import java.util.Collection;
import java.util.List;
/**
* @author max
* @author yole
*/
@TestDataPath("$CONTENT_ROOT/../testData/stubs/")
public class PyStubsTest extends PyLightFixtureTestCase {
@@ -316,7 +317,11 @@ public class PyStubsTest extends PyLightFixtureTestCase {
}
public void testIfNameMain() { // PY-4008
final PyFileImpl file = (PyFileImpl) getTestFile();
ensureVariableNotInIndex("xyzzy");
assertNotParsed(file);
file.acceptChildren(new PyRecursiveElementVisitor()); // assert no error on switching from stub to AST
assertNotNull(file.getTreeElement());
}
public void testVariableInComprehension() { // PY-4029
@@ -66,6 +66,10 @@ public class PyRenameTest extends PyLightFixtureTestCase {
doTest("bar");
}
public void testEpydocRenameType() {
doTest("Shazam");
}
public void testRenameGlobalWithoutToplevel() { // PY-3547
doTest("bar");
}