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