mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/ultimate
This commit is contained in:
@@ -41,7 +41,7 @@ public class PythonFoldingBuilder implements FoldingBuilder, DumbAware {
|
||||
while (lastImport.getElementType() == TokenType.WHITE_SPACE) {
|
||||
lastImport = lastImport.getTreePrev();
|
||||
}
|
||||
if (isImport(lastImport, false)) {
|
||||
if (isImport(lastImport, false) && firstImport != lastImport) {
|
||||
descriptors.add(new FoldingDescriptor(firstImport, new TextRange(firstImport.getStartOffset(),
|
||||
lastImport.getTextRange().getEndOffset())));
|
||||
}
|
||||
|
||||
@@ -15,10 +15,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
* User: dcheryasov
|
||||
* Date: Apr 24, 2009 3:17:59 AM
|
||||
*/
|
||||
// intentional package level access
|
||||
class AddImportHelper {
|
||||
public class AddImportHelper {
|
||||
private static final Logger LOG = Logger.getInstance("#" + AddImportHelper.class.getName());
|
||||
|
||||
private AddImportHelper() {
|
||||
}
|
||||
|
||||
private static PsiElement getInsertPosition(final PsiFile file) {
|
||||
PsiElement feeler = file.getFirstChild();
|
||||
LOG.assertTrue(feeler != null);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.jetbrains.python.actions;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilBase;
|
||||
import com.intellij.codeInsight.template.TemplateBuilder;
|
||||
import com.intellij.codeInsight.template.TemplateBuilderFactory;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyElementGenerator;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class CreateClassQuickFix implements LocalQuickFix {
|
||||
private final String myClassName;
|
||||
private final PsiElement myAnchor;
|
||||
|
||||
public CreateClassQuickFix(String className, PsiElement anchor) {
|
||||
myClassName = className;
|
||||
myAnchor = anchor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return "Create class '" + myClassName + "'";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return "Create Class";
|
||||
}
|
||||
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement anchor = myAnchor;
|
||||
while(!(anchor.getParent() instanceof PyFile)) {
|
||||
anchor = anchor.getParent();
|
||||
}
|
||||
PyClass pyClass = PyElementGenerator.getInstance(myAnchor.getProject()).createFromText(PyClass.class,
|
||||
"class " + myClassName + "(object):\n pass");
|
||||
pyClass = (PyClass) anchor.getParent().addBefore(pyClass, anchor);
|
||||
pyClass = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(pyClass);
|
||||
TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(pyClass);
|
||||
builder.replaceElement(pyClass.getSuperClassExpressions() [0], "object");
|
||||
builder.replaceElement(pyClass.getStatementList(), "pass");
|
||||
builder.run();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -199,13 +199,13 @@ public class PyBlock implements ASTBlock {
|
||||
IElementType type2 = childNode2.getElementType();
|
||||
|
||||
if (type1 == PyElementTypes.CLASS_DECLARATION) {
|
||||
int blankLines = mySettings.BLANK_LINES_AROUND_CLASS + 1;
|
||||
return Spacing.createSpacing(0, 0, blankLines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
|
||||
return getBlankLinesForOption(mySettings.BLANK_LINES_AROUND_CLASS);
|
||||
}
|
||||
|
||||
if (type1 == PyElementTypes.FUNCTION_DECLARATION || (type2 == PyElementTypes.FUNCTION_DECLARATION && type1 == PyElementTypes.CLASS_DECLARATION)) {
|
||||
int blankLines = mySettings.BLANK_LINES_AROUND_METHOD + 1;
|
||||
return Spacing.createSpacing(0, 0, blankLines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
|
||||
return getBlankLinesForOption(mySettings.BLANK_LINES_AROUND_METHOD);
|
||||
}
|
||||
if (isImportStatement(type1) && (isStatementOrDeclaration(type2) && !isImportStatement(type2))) {
|
||||
return getBlankLinesForOption(mySettings.BLANK_LINES_AFTER_IMPORTS);
|
||||
}
|
||||
|
||||
if (isStatementOrDeclaration(type1) && isStatementOrDeclaration(type2)) {
|
||||
@@ -299,6 +299,10 @@ public class PyBlock implements ASTBlock {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isImportStatement(IElementType type1) {
|
||||
return (type1 == PyElementTypes.IMPORT_STATEMENT || type1 == PyElementTypes.FROM_IMPORT_STATEMENT);
|
||||
}
|
||||
|
||||
private static boolean isAround(IElementType type1, IElementType type2, final TokenSet tokenSet) {
|
||||
return tokenSet.contains(type1) || tokenSet.contains(type2);
|
||||
}
|
||||
@@ -307,6 +311,11 @@ public class PyBlock implements ASTBlock {
|
||||
return mySettings.getCustomSettings(PyCodeStyleSettings.class);
|
||||
}
|
||||
|
||||
private Spacing getBlankLinesForOption(final int option) {
|
||||
int blankLines = option + 1;
|
||||
return Spacing.createSpacing(0, 0, blankLines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
|
||||
}
|
||||
|
||||
private Spacing getSpacingForOption(boolean isOptionSet) {
|
||||
int spaces = isOptionSet ? 1 : 0;
|
||||
return Spacing.createSpacing(spaces, spaces, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
|
||||
@@ -406,6 +406,9 @@ public class PyUnresolvedReferencesInspection extends LocalInspectionTool {
|
||||
if (ref_element != null && ref_is_importable && hint_action == null) {
|
||||
actions.add(new AddImportAction(reference));
|
||||
}
|
||||
if (ref_text.length() > 2 && Character.isUpperCase(ref_text.charAt(0)) && !Character.isUpperCase(ref_text.charAt(1))) {
|
||||
actions.add(new CreateClassQuickFix(ref_text, reference.getElement()));
|
||||
}
|
||||
}
|
||||
}
|
||||
String description = description_buf.toString();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.jetbrains.python.refactoring.introduce;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilBase;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
@@ -39,7 +40,7 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
|
||||
PyExpressionStatement statement = PsiTreeUtil.getParentOfType(expression, PyExpressionStatement.class);
|
||||
if (statement != null) {
|
||||
if (statement.getExpression() == expression) {
|
||||
expression.delete();
|
||||
statement.delete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -85,7 +86,7 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
|
||||
return ArrayUtil.toStringArray(res);
|
||||
}
|
||||
|
||||
protected void performAction(@NotNull final Project project, Editor editor, PsiFile file, String name, boolean replaceAll, boolean hasConstructor) {
|
||||
public void performAction(@NotNull final Project project, Editor editor, PsiFile file, String name, boolean replaceAll, boolean hasConstructor) {
|
||||
if (!CommonRefactoringUtil.checkReadOnlyStatus(file)) {
|
||||
return;
|
||||
}
|
||||
@@ -145,10 +146,13 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
|
||||
initInConstructor = dialog.initInConstructor();
|
||||
}
|
||||
String assignmentText = name + " = " + expression.getText();
|
||||
final PyAssignmentStatement declaration = createDeclaration(project, assignmentText);
|
||||
PyAssignmentStatement declaration = createDeclaration(project, assignmentText);
|
||||
|
||||
assert name != null;
|
||||
performReplace(project, declaration, expression, occurrences, name, replaceAll, initInConstructor);
|
||||
declaration = performReplace(project, declaration, expression, occurrences, name, replaceAll, initInConstructor);
|
||||
declaration = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(declaration);
|
||||
editor.getCaretModel().moveToOffset(declaration.getTextRange().getEndOffset());
|
||||
editor.getSelectionModel().removeSelection();
|
||||
}
|
||||
|
||||
protected abstract String getHelpId();
|
||||
@@ -172,24 +176,24 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
|
||||
return PyRefactoringUtil.getOccurences(expression, context);
|
||||
}
|
||||
|
||||
private void performReplace(@NotNull final Project project,
|
||||
@NotNull final PyAssignmentStatement declaration,
|
||||
@NotNull final PsiElement expression,
|
||||
@NotNull final List<PsiElement> occurrences,
|
||||
@NotNull final String name,
|
||||
final boolean replaceAll,
|
||||
final boolean initInConstructor) {
|
||||
new WriteCommandAction(project, expression.getContainingFile()) {
|
||||
protected void run(final Result result) throws Throwable {
|
||||
private PyAssignmentStatement performReplace(@NotNull final Project project,
|
||||
@NotNull final PyAssignmentStatement declaration,
|
||||
@NotNull final PsiElement expression,
|
||||
@NotNull final List<PsiElement> occurrences,
|
||||
@NotNull final String name,
|
||||
final boolean replaceAll,
|
||||
final boolean initInConstructor) {
|
||||
return new WriteCommandAction<PyAssignmentStatement>(project, expression.getContainingFile()) {
|
||||
protected void run(final Result<PyAssignmentStatement> result) throws Throwable {
|
||||
final Pair<PsiElement, TextRange> data = expression.getUserData(PyPsiUtils.SELECTION_BREAKS_AST_NODE);
|
||||
if (data == null) {
|
||||
addDeclaration(expression, declaration, occurrences, replaceAll, initInConstructor);
|
||||
result.setResult((PyAssignmentStatement)addDeclaration(expression, declaration, occurrences, replaceAll, initInConstructor));
|
||||
}
|
||||
else {
|
||||
addDeclaration(data.first, declaration, occurrences, replaceAll, initInConstructor);
|
||||
result.setResult((PyAssignmentStatement)addDeclaration(data.first, declaration, occurrences, replaceAll, initInConstructor));
|
||||
}
|
||||
|
||||
PyExpression newExpression = createExpression(project, name, declaration).getExpression();
|
||||
PyExpression newExpression = createExpression(project, name, declaration);
|
||||
|
||||
if (replaceAll) {
|
||||
for (PsiElement occurrence : occurrences) {
|
||||
@@ -200,11 +204,11 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
|
||||
replaceExpression(newExpression, project, expression);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}.execute().getResultObject();
|
||||
}
|
||||
|
||||
protected PyExpressionStatement createExpression(Project project, String name, PyAssignmentStatement declaration) {
|
||||
return PyElementGenerator.getInstance(project).createFromText(PyExpressionStatement.class, name);
|
||||
protected PyExpression createExpression(Project project, String name, PyAssignmentStatement declaration) {
|
||||
return PyElementGenerator.getInstance(project).createExpressionFromText(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+2
-2
@@ -60,10 +60,10 @@ public class FieldIntroduceHandler extends IntroduceHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PyExpressionStatement createExpression(Project project, String name, PyAssignmentStatement declaration) {
|
||||
protected PyExpression createExpression(Project project, String name, PyAssignmentStatement declaration) {
|
||||
final String text = declaration.getText();
|
||||
final String self_name = text.substring(0, text.indexOf('.'));
|
||||
return PyElementGenerator.getInstance(project).createFromText(PyExpressionStatement.class, self_name + "." + name);
|
||||
return PyElementGenerator.getInstance(project).createExpressionFromText(self_name + "." + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -36,8 +36,7 @@ public class VariableIntroduceHandler extends IntroduceHandler {
|
||||
PsiElement anchor = replaceAll ? findAnchor(occurrences) : PsiTreeUtil.getParentOfType(expression, PyStatement.class);
|
||||
assert anchor != null;
|
||||
final PsiElement parent = anchor.getParent();
|
||||
parent.addBefore(declaration, anchor);
|
||||
return parent.getParent();
|
||||
return parent.addBefore(declaration, anchor);
|
||||
}
|
||||
|
||||
private static PsiElement findAnchor(List<PsiElement> occurrences) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
this is commented
|
||||
@@ -0,0 +1 @@
|
||||
# this is commented
|
||||
@@ -0,0 +1,3 @@
|
||||
import sys
|
||||
from os import *
|
||||
def foo(): print sys.platform
|
||||
@@ -0,0 +1,4 @@
|
||||
import sys
|
||||
from os import *
|
||||
|
||||
def foo(): print sys.platform
|
||||
@@ -0,0 +1,3 @@
|
||||
class XyzzyTest:
|
||||
def testSimple(self):
|
||||
c = <caret><warning descr="Unresolved reference 'Xyzzy'">Xyzzy</warning>()
|
||||
@@ -0,0 +1,6 @@
|
||||
class Xyzzy(object):
|
||||
pass
|
||||
|
||||
class XyzzyTest:
|
||||
def testSimple(self):
|
||||
c = Xyzzy()
|
||||
@@ -1,6 +1,7 @@
|
||||
# Comments here
|
||||
"Doc comment stays intact"
|
||||
import ImportTarget
|
||||
|
||||
ImportTarget.foo
|
||||
|
||||
foo = 1
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"Doc comment stays intact"
|
||||
import ImportTarget
|
||||
|
||||
ImportTarget.foo
|
||||
|
||||
foo = 1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import ImportTarget
|
||||
|
||||
ImportTarget.foo
|
||||
|
||||
foo = 1
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
def foo():
|
||||
a = 1<caret>
|
||||
print "fooo"
|
||||
@@ -0,0 +1,3 @@
|
||||
def foo():
|
||||
<selection>1</selection>
|
||||
print "fooo"
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
@@ -81,6 +85,19 @@ public class PyEditingTest extends PyLightFixtureTestCase {
|
||||
myFixture.checkResultByFile("/editing/smartUnindent.after.py", true);
|
||||
}
|
||||
|
||||
public void testUncommentWithSpace() throws Exception { // PY-980
|
||||
myFixture.configureByFile("/editing/uncommentWithSpace.before.py");
|
||||
myFixture.getEditor().getCaretModel().moveToLogicalPosition(new LogicalPosition(0, 1));
|
||||
CommandProcessor.getInstance().executeCommand(myFixture.getProject(), new Runnable() {
|
||||
public void run() {
|
||||
CommentByLineCommentAction action = new CommentByLineCommentAction();
|
||||
action.actionPerformed(new AnActionEvent(null, DataManager.getInstance().getDataContext(), "", action.getTemplatePresentation(),
|
||||
ActionManager.getInstance(), 0));
|
||||
}
|
||||
}, "", null);
|
||||
myFixture.checkResultByFile("/editing/uncommentWithSpace.after.py", true);
|
||||
}
|
||||
|
||||
private String doTestTyping(final String text, final int offset, final char character) {
|
||||
final PsiFile file = ApplicationManager.getApplication().runWriteAction(new Computable<PsiFile>() {
|
||||
public PsiFile compute() {
|
||||
|
||||
@@ -36,6 +36,10 @@ public class PyFormatterTest extends PyLightFixtureTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testBlankLineAfterImports() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
myFixture.configureByFile("formatter/" + getTestName(true) + ".py");
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
|
||||
@@ -140,6 +140,10 @@ public class PyQuickFixTest extends PyLightFixtureTestCase {
|
||||
PyBundle.message("QFIX.replace.equality"), true, true);
|
||||
}
|
||||
|
||||
public void testAddClassFix() throws Exception {
|
||||
doInspectionTest("AddClass.py", PyUnresolvedReferencesInspection.class, "Create class 'Xyzzy'", true, true);
|
||||
}
|
||||
|
||||
@NonNls
|
||||
protected String getTestDataPath() {
|
||||
return PythonTestUtil.getTestDataPath() + "/inspections/";
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.jetbrains.python.refactoring.PyCodeFragmentTest;
|
||||
import com.jetbrains.python.refactoring.PyExtractMethodTest;
|
||||
import com.jetbrains.python.refactoring.PyInlineLocalTest;
|
||||
import com.jetbrains.python.refactoring.PyRenameTest;
|
||||
import com.jetbrains.python.refactoring.*;
|
||||
import com.jetbrains.python.refactoring.classes.PyExtractSuperclassTest;
|
||||
import com.jetbrains.python.refactoring.classes.PyPullUpTest;
|
||||
import com.jetbrains.python.refactoring.classes.PyPushDownTest;
|
||||
@@ -56,7 +53,8 @@ public class PythonAllTestsSuite {
|
||||
PyCodeFragmentTest.class,
|
||||
PyOptimizeImportsTest.class,
|
||||
PySmartEnterTest.class,
|
||||
PyStatementMoverTest.class
|
||||
PyStatementMoverTest.class,
|
||||
PyIntroduceVariableTest.class
|
||||
};
|
||||
|
||||
public static TestSuite suite() {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.jetbrains.python.refactoring;
|
||||
|
||||
import com.jetbrains.python.fixtures.PyLightFixtureTestCase;
|
||||
import com.jetbrains.python.refactoring.introduce.variable.VariableIntroduceHandler;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyIntroduceVariableTest extends PyLightFixtureTestCase {
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return super.getTestDataPath() + "/refactoring/introduceVariable";
|
||||
}
|
||||
|
||||
public void testSimple() throws Exception {
|
||||
myFixture.configureByFile("simple.py");
|
||||
VariableIntroduceHandler handler = new VariableIntroduceHandler();
|
||||
handler.performAction(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile(), "a", true, false);
|
||||
myFixture.checkResultByFile("simple.after.py");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user