diff --git a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateAction.java b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateAction.java index 66675dc0b8..081b370027 100644 --- a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateAction.java +++ b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateAction.java @@ -8,23 +8,12 @@ import java.util.List; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; -import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.ui.IEditorActionDelegate; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.texteditor.ITextEditor; import org.python.pydev.ast.refactoring.RefactoringInfo; import org.python.pydev.core.IPyEdit; -import org.python.pydev.core.log.Log; -import org.python.pydev.shared_core.SharedCorePlugin; import org.python.pydev.shared_core.code_completion.ICompletionProposalHandle; -import org.python.pydev.shared_ui.EditorUtils; -public abstract class AbstractPyCreateAction extends Action implements IEditorActionDelegate { +public abstract class AbstractPyCreateAction { public static final int LOCATION_STRATEGY_BEFORE_CURRENT = 0; //before the current method (in the same level) public static final int LOCATION_STRATEGY_END = 1; //end of file or end of class @@ -36,52 +25,6 @@ public void setActiveEditor(IAction action, IPyEdit edit) { this.targetEditor = edit; } - @Override - public void setActiveEditor(IAction action, IEditorPart targetEditor) { - if (targetEditor instanceof ITextEditor) { - if (targetEditor instanceof IPyEdit) { - this.targetEditor = (IPyEdit) targetEditor; - } else { - this.targetEditor = null; - Log.log(new RuntimeException("Editor not a PyEdit.")); - } - } - } - - @Override - public void selectionChanged(IAction action, ISelection selection) { - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) - */ - @Override - public void run(IAction action) { - if (targetEditor == null) { - Status status = SharedCorePlugin.makeStatus(IStatus.ERROR, "Unable to do refactoring.", null); - ErrorDialog.openError(EditorUtils.getShell(), "Unable to do refactoring.", - "Target editor is null (not PyEdit).", status); - return; - } - - try { - RefactoringInfo refactoringInfo = new RefactoringInfo(targetEditor); - execute(refactoringInfo, LOCATION_STRATEGY_BEFORE_CURRENT); - } catch (Throwable e) { - Log.log(e); - Throwable initial = e; - while (e.getCause() != null) { - e = e.getCause(); - } - //get the root cause - Status status = SharedCorePlugin.makeStatus(IStatus.ERROR, "Error making refactoring", initial); - ErrorDialog.openError(EditorUtils.getShell(), "Error making refactoring", e.getMessage(), status); - } - } - - public abstract void execute(RefactoringInfo refactoringInfo, int locationStrategyBeforeCurrent); - public abstract ICompletionProposalHandle createProposal(RefactoringInfo refactoringInfo, String actTok, int locationStrategy, List parametersAfterCall); diff --git a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateClassOrMethodOrField.java b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateClassOrMethodOrField.java index 6274a334d4..8a71b7b309 100644 --- a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateClassOrMethodOrField.java +++ b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/AbstractPyCreateClassOrMethodOrField.java @@ -9,28 +9,21 @@ import java.util.List; import org.eclipse.core.runtime.Assert; -import org.eclipse.jface.dialogs.IInputValidator; -import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Region; -import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; -import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.eclipse.jface.text.templates.Template; -import org.eclipse.jface.text.templates.TemplateContextType; import org.python.pydev.ast.adapters.IClassDefAdapter; import org.python.pydev.ast.adapters.ModuleAdapter; import org.python.pydev.ast.adapters.offsetstrategy.BeginOffset; import org.python.pydev.ast.adapters.offsetstrategy.EndOffset; import org.python.pydev.ast.adapters.offsetstrategy.IOffsetStrategy; -import org.python.pydev.ast.refactoring.RefactoringInfo; +import org.python.pydev.ast.assist_assign.AssistAssign; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.PySelection.LineStartingScope; import org.python.pydev.core.docutils.PyStringUtils; import org.python.pydev.core.log.Log; import org.python.pydev.core.proposals.CompletionProposalFactory; import org.python.pydev.core.templates.PyDocumentTemplateContext; -import org.python.pydev.editor.PyEdit; -import org.python.pydev.editor.correctionassist.heuristics.AssistAssign; import org.python.pydev.parser.jython.ast.ClassDef; import org.python.pydev.parser.jython.ast.Pass; import org.python.pydev.parser.visitors.NodeUtils; @@ -38,73 +31,12 @@ import org.python.pydev.shared_core.string.FastStringBuffer; import org.python.pydev.shared_core.string.StringUtils; import org.python.pydev.shared_core.structure.Tuple; -import org.python.pydev.shared_ui.EditorUtils; public abstract class AbstractPyCreateClassOrMethodOrField extends AbstractPyCreateAction { public abstract String getCreationStr(); - @Override - public void execute(RefactoringInfo refactoringInfo, int locationStrategy) { - try { - String creationStr = this.getCreationStr(); - final String asTitle = StringUtils.getWithFirstUpper(creationStr); - - PySelection pySelection = refactoringInfo.getPySelection(); - Tuple currToken = pySelection.getCurrToken(); - String actTok = currToken.o1; - List parametersAfterCall = null; - if (actTok.length() == 0) { - InputDialog dialog = new InputDialog(EditorUtils.getShell(), asTitle + " name", - "Please enter the name of the " + asTitle + " to be created.", "", new IInputValidator() { - - @Override - public String isValid(String newText) { - if (newText.length() == 0) { - return "The " + asTitle + " name may not be empty"; - } - if (StringUtils.containsWhitespace(newText)) { - return "The " + asTitle + " name may not contain whitespaces."; - } - return null; - } - }); - if (dialog.open() != InputDialog.OK) { - return; - } - actTok = dialog.getValue(); - } else { - parametersAfterCall = pySelection.getParametersAfterCall(currToken.o2 + actTok.length()); - - } - - execute(refactoringInfo, actTok, parametersAfterCall, locationStrategy); - } catch (BadLocationException e) { - Log.log(e); - } - } - - /** - * When executed it'll create a proposal and apply it. - */ - /*default*/void execute(RefactoringInfo refactoringInfo, String actTok, List parametersAfterCall, - int locationStrategy) { - try { - ICompletionProposalHandle proposal = createProposal(refactoringInfo, actTok, locationStrategy, - parametersAfterCall); - if (proposal != null) { - if (proposal instanceof ICompletionProposalExtension2) { - ICompletionProposalExtension2 extension2 = (ICompletionProposalExtension2) proposal; - extension2.apply(((PyEdit) targetEditor).getPySourceViewer(), '\n', 0, 0); - } else { - proposal.apply(refactoringInfo.getDocument()); - } - } - - } catch (Exception e) { - Log.log(e); - } - } + protected abstract String getDefaultActTok(); protected ICompletionProposalHandle createProposal(PySelection pySelection, String source, Tuple offsetAndIndent) { @@ -176,10 +108,8 @@ protected ICompletionProposalHandle createProposal(PySelection pySelection, Stri //Note: was using new PyContextType(), but when we had something as ${user} it //would end up replacing it with the actual name of the user, which is not what //we want! - TemplateContextType contextType = new TemplateContextType(); - contextType.addResolver(new GlobalTemplateVariables.Cursor()); //We do want the cursor thought. - PyDocumentTemplateContext context = PyDocumentTemplateContext.createContext(contextType, - targetEditor, region, indent); + PyDocumentTemplateContext context = PyDocumentTemplateContext.createContextWithCursor(targetEditor, region, + indent); Template template = new Template("Create " + creationStr, "Create " + creationStr, "", source, true); ICompletionProposalHandle templateProposal = CompletionProposalFactory.get() diff --git a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/NullPyCreateAction.java b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/NullPyCreateAction.java index 630993b2ae..b34cabf63e 100644 --- a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/NullPyCreateAction.java +++ b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/NullPyCreateAction.java @@ -13,11 +13,6 @@ public class NullPyCreateAction extends AbstractPyCreateAction { - @Override - public void execute(RefactoringInfo refactoringInfo, int locationStrategyBeforeCurrent) { - - } - @Override public ICompletionProposalHandle createProposal(RefactoringInfo refactoringInfo, String actTok, int locationStrategy, diff --git a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateClass.java b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateClass.java index d15a92a727..a2c49144e7 100644 --- a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateClass.java +++ b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateClass.java @@ -43,6 +43,11 @@ public String getCreationStr() { return "class"; } + @Override + protected String getDefaultActTok() { + return "MyClass"; + } + /** * Returns a proposal that can be used to generate the code. */ diff --git a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateMethodOrField.java b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateMethodOrField.java index 8f3a6bfef6..c85b4b4a98 100644 --- a/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateMethodOrField.java +++ b/plugins/com.python.pydev.refactoring/src/com/python/pydev/refactoring/tdd/PyCreateMethodOrField.java @@ -48,6 +48,17 @@ public String getCreationStr() { return "method"; } + @Override + protected String getDefaultActTok() { + if (createAs == FIELD) { + return "my_field"; + } + if (createAs == CONSTANT) { + return "my_constant"; + } + return "my_method"; + } + /** * Returns a proposal that can be used to generate the code. */ diff --git a/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/ExecutePyCreate.java b/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/ExecutePyCreate.java new file mode 100644 index 0000000000..c5b15d12cf --- /dev/null +++ b/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/ExecutePyCreate.java @@ -0,0 +1,78 @@ +package com.python.pydev.refactoring.tdd; + +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; +import org.python.pydev.ast.refactoring.RefactoringInfo; +import org.python.pydev.core.docutils.PySelection; +import org.python.pydev.core.log.Log; +import org.python.pydev.shared_core.code_completion.ICompletionProposalHandle; +import org.python.pydev.shared_core.structure.Tuple; + +public class ExecutePyCreate { + + public static void execute(AbstractPyCreateClassOrMethodOrField action, RefactoringInfo refactoringInfo, + int locationStrategy) { + try { + PySelection pySelection = refactoringInfo.getPySelection(); + Tuple currToken = pySelection.getCurrToken(); + String actTok = currToken.o1; + List parametersAfterCall = null; + if (actTok.length() == 0) { + actTok = action.getDefaultActTok(); + // String creationStr = this.getCreationStr(); + // final String asTitle = StringUtils.getWithFirstUpper(creationStr); + // InputDialog dialog = new InputDialog(EditorUtils.getShell(), asTitle + " name", + // "Please enter the name of the " + asTitle + " to be created.", "", new IInputValidator() { + // + // @Override + // public String isValid(String newText) { + // if (newText.length() == 0) { + // return "The " + asTitle + " name may not be empty"; + // } + // if (StringUtils.containsWhitespace(newText)) { + // return "The " + asTitle + " name may not contain whitespaces."; + // } + // return null; + // } + // }); + // if (dialog.open() != InputDialog.OK) { + // return; + // } + // actTok = dialog.getValue(); + } else { + parametersAfterCall = pySelection.getParametersAfterCall(currToken.o2 + actTok.length()); + + } + + execute(action, refactoringInfo, actTok, parametersAfterCall, locationStrategy); + } catch (BadLocationException e) { + Log.log(e); + } + } + + /** + * When executed it'll create a proposal and apply it. + */ + public static void execute(AbstractPyCreateClassOrMethodOrField action, RefactoringInfo refactoringInfo, + String actTok, List parametersAfterCall, + int locationStrategy) { + try { + ICompletionProposalHandle proposal = action.createProposal(refactoringInfo, actTok, locationStrategy, + parametersAfterCall); + if (proposal != null) { + if (proposal instanceof ICompletionProposalExtension2) { + ICompletionProposalExtension2 extension2 = (ICompletionProposalExtension2) proposal; + extension2.apply(null, '\n', 0, 0); + } else { + proposal.apply(refactoringInfo.getDocument()); + } + } + + } catch (Exception e) { + Log.log(e); + } + } + +} diff --git a/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateClassTest.java b/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateClassTest.java index 1f19e17540..f4b20e79e6 100644 --- a/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateClassTest.java +++ b/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateClassTest.java @@ -67,7 +67,7 @@ public void testPyCreateClassInSameModule() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, 0, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "class MyClass(${object}):\n" + @@ -95,7 +95,7 @@ public void testPyCreateClassInSameModule4() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, document.getLength() - 5, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "#=============\n" + @@ -132,7 +132,7 @@ public void testPyCreateClassInSameModule5() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, document.getLength() - 5, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "a = 10\n" + @@ -168,7 +168,7 @@ public void testPyCreateClassInSameModule6() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, document.getLength() - 5, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "a = 10\n" + @@ -196,7 +196,7 @@ public void testPyCreateClassWithParameters() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, 0, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "class MyClass(${object}):\n" + @@ -219,7 +219,7 @@ public void testPyCreateClassWithParameters2() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, 0, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "class MyClass(${object}):\n" + @@ -248,7 +248,7 @@ public void testPyCreateClassInSameModule2() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, source.length() - 4, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "import foo\n" + @@ -280,7 +280,7 @@ public void testPyCreateClassInSameModule3() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, source.length() - 4, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "import foo\n" + @@ -317,7 +317,7 @@ public void testPyCreateClassEndOfFile() throws Exception { ICoreTextSelection selection = new CoreTextSelection(document, source.length() - 4, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateClass.execute(info, PyCreateClass.LOCATION_STRATEGY_END); + ExecutePyCreate.execute(pyCreateClass, info, PyCreateClass.LOCATION_STRATEGY_END); assertContentsEqual("" + "import foo\n" + diff --git a/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateMethodTest.java b/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateMethodTest.java index 5ea275f99e..c1ed56c2c5 100644 --- a/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateMethodTest.java +++ b/plugins/com.python.pydev.refactoring/tests/com/python/pydev/refactoring/tdd/PyCreateMethodTest.java @@ -67,7 +67,7 @@ public void testPyCreateMethodGlobal() { ICoreTextSelection selection = new CoreTextSelection(document, 0, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateMethod.execute(info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateMethod, info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "def MyMethod():\n" + @@ -87,7 +87,7 @@ public void testPyCreateMethodGlobalParams() { ICoreTextSelection selection = new CoreTextSelection(document, 0, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateMethod.execute(info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateMethod, info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + "def MyMethod(${a}, ${b}):\n" + @@ -107,7 +107,7 @@ public void testPyCreateMethodGlobal1() { ICoreTextSelection selection = new CoreTextSelection(document, 5, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateMethod.execute(info, AbstractPyCreateAction.LOCATION_STRATEGY_END); + ExecutePyCreate.execute(pyCreateMethod, info, AbstractPyCreateAction.LOCATION_STRATEGY_END); assertContentsEqual("" + "a = MyMethod()\n" + @@ -128,7 +128,8 @@ public void testPyCreateMethodInEmptyDoc() { ICoreTextSelection selection = new CoreTextSelection(document, 5, 0); RefactoringInfo info = new RefactoringInfo(document, selection, PY_27_ONLY_GRAMMAR_VERSION_PROVIDER); - pyCreateMethod.execute(info, "MyMethod", new ArrayList(), AbstractPyCreateAction.LOCATION_STRATEGY_END); + ExecutePyCreate.execute(pyCreateMethod, info, "MyMethod", new ArrayList(), + AbstractPyCreateAction.LOCATION_STRATEGY_END); assertContentsEqual("" + "def MyMethod():\n" + @@ -138,7 +139,7 @@ public void testPyCreateMethodInEmptyDoc() { "", document.get()); document.set(""); - pyCreateMethod.execute(info, "MyMethod2", new ArrayList(), + ExecutePyCreate.execute(pyCreateMethod, info, "MyMethod2", new ArrayList(), AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); assertContentsEqual("" + @@ -164,7 +165,7 @@ public void testPyCreateMethodInClass() { pyCreateMethod.setCreateInClass("A"); pyCreateMethod.setCreateAs(PyCreateMethodOrField.CLASSMETHOD); - pyCreateMethod.execute(info, AbstractPyCreateAction.LOCATION_STRATEGY_END); + ExecutePyCreate.execute(pyCreateMethod, info, AbstractPyCreateAction.LOCATION_STRATEGY_END); assertContentsEqual("" + "" + @@ -198,7 +199,7 @@ public void testPyCreateMethodInSelfWithDecorator() { pyCreateMethod.setCreateInClass("A"); pyCreateMethod.setCreateAs(PyCreateMethodOrField.BOUND_METHOD); - pyCreateMethod.execute(info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateMethod, info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); String expected = "" + "class A(object):\n" + @@ -233,7 +234,7 @@ public void testPyCreateMethod() { pyCreateMethod.setCreateInClass("A"); pyCreateMethod.setCreateAs(PyCreateMethodOrField.BOUND_METHOD); - pyCreateMethod.execute(info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateMethod, info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); String expected = "" + "class A(object):\n" + @@ -267,7 +268,7 @@ public void testPyCreateMethodWithTabs() { pyCreateMethod.setCreateInClass("A"); pyCreateMethod.setCreateAs(PyCreateMethodOrField.BOUND_METHOD); - pyCreateMethod.execute(info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); + ExecutePyCreate.execute(pyCreateMethod, info, AbstractPyCreateAction.LOCATION_STRATEGY_BEFORE_CURRENT); String expected = "" + "class A(object):\n" + diff --git a/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF b/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF index cc80eef98d..7f0920ac1f 100644 --- a/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF +++ b/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF @@ -22,6 +22,7 @@ Export-Package: org.python.pydev.ast, org.python.pydev.ast.adapters.visitors.selection, org.python.pydev.ast.analysis, org.python.pydev.ast.analysis.messages, + org.python.pydev.ast.assist_assign, org.python.pydev.ast.builder, org.python.pydev.ast.codecompletion, org.python.pydev.ast.codecompletion.revisited, diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistAssign.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/assist_assign/AssistAssign.java similarity index 71% rename from plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistAssign.java rename to plugins/org.python.pydev.ast/src/org/python/pydev/ast/assist_assign/AssistAssign.java index 12b21d0edf..1b1be53c1a 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistAssign.java +++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/assist_assign/AssistAssign.java @@ -9,27 +9,32 @@ * * @author Fabio Zadrozny */ -package org.python.pydev.editor.correctionassist.heuristics; +package org.python.pydev.ast.assist_assign; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.source.ISourceViewer; -import org.python.pydev.codingstd.ICodingStd; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.templates.TemplateContext; +import org.eclipse.jface.text.templates.TemplateContextType; import org.python.pydev.core.IAssistProps; +import org.python.pydev.core.ICodingStd; +import org.python.pydev.core.IIndentPrefs; import org.python.pydev.core.IPyEdit; import org.python.pydev.core.IPythonNature; +import org.python.pydev.core.autoedit.DefaultIndentPrefs; import org.python.pydev.core.docutils.ParsingUtils; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.PyStringUtils; import org.python.pydev.core.docutils.SyntaxErrorException; import org.python.pydev.core.log.Log; +import org.python.pydev.core.preferences.PyDevCodeStylePreferences; import org.python.pydev.core.proposals.CompletionProposalFactory; -import org.python.pydev.editor.PyEdit; -import org.python.pydev.editor.codefolding.PySourceViewer; -import org.python.pydev.plugin.preferences.PyCodeStylePreferencesPage; +import org.python.pydev.core.templates.PyAddTemplateResolvers; +import org.python.pydev.core.templates.PyDocumentTemplateContext; import org.python.pydev.shared_core.code_completion.ICompletionProposalHandle; import org.python.pydev.shared_core.code_completion.IPyCompletionProposal; import org.python.pydev.shared_core.image.IImageCache; @@ -51,7 +56,7 @@ public AssistAssign() { @Override public boolean localsAndAttrsCamelcase() { - return PyCodeStylePreferencesPage.useLocalsAndAttrsCamelCase(); + return PyDevCodeStylePreferences.useLocalsAndAttrsCamelCase(); } }); @@ -73,26 +78,17 @@ private IImageHandle getImage(IImageCache imageCache, String c) { */ @Override public List getProps(PySelection ps, IImageCache imageCache, File f, - IPythonNature nature, - IPyEdit edit, int offset) throws BadLocationException { - PySourceViewer viewer = null; - if (edit != null) { //only in tests it's actually null - viewer = ((PyEdit) edit).getPySourceViewer(); - } - - return this.getProps(ps, imageCache, viewer, offset, TextSelectionUtils.getLineWithoutComments(ps), - PySelection.getFirstCharPosition(ps.getDoc(), ps.getAbsoluteCursorOffset())); + IPythonNature nature, IPyEdit edit, int offset) throws BadLocationException { + return this.getProps(ps, imageCache, edit, offset, TextSelectionUtils.getLineWithoutComments(ps), + PySelection.getFirstCharPosition(ps.getDoc(), ps.getAbsoluteCursorOffset()), nature); } /** - * Actual implementation (receiving a source viewer and only the actually used parameters). - * - * @see org.python.pydev.core.IAssistProps#getProps - * * @param lineWithoutComments the line that should be checked (without any comments) */ - public List getProps(PySelection ps, IImageCache imageCache, ISourceViewer sourceViewer, - int offset, String lineWithoutComments, int firstCharAbsolutePosition) throws BadLocationException { + public List getProps(PySelection ps, IImageCache imageCache, IPyEdit edit, + int offset, String lineWithoutComments, int firstCharAbsolutePosition, IPythonNature nature) + throws BadLocationException { List l = new ArrayList<>(); if (lineWithoutComments.trim().length() == 0) { @@ -143,20 +139,53 @@ public List getProps(PySelection ps, IImageCache imag if (loc.startsWith("_")) { loc = loc.substring(1); } - l.add(CompletionProposalFactory.get().createAssistAssignCompletionProposal(loc + " = ", - firstCharAbsolutePosition, 0, 0, getImage(imageCache, - UIConstants.ASSIST_ASSIGN_TO_LOCAL), - "Assign to local (" + loc + ")", null, null, IPyCompletionProposal.PRIORITY_DEFAULT, sourceViewer, - null)); - - l.add(CompletionProposalFactory.get().createAssistAssignCompletionProposal("self." + callName + " = ", - firstCharAbsolutePosition, 0, 5, getImage( - imageCache, UIConstants.ASSIST_ASSIGN_TO_CLASS), - "Assign to field (self." + callName + ")", null, null, IPyCompletionProposal.PRIORITY_DEFAULT, - sourceViewer, null)); + + IIndentPrefs indentPrefs = edit != null ? edit.getIndentPrefs() : null; + if (indentPrefs == null) { + indentPrefs = DefaultIndentPrefs.get(nature); + } + + // Unfortunately in the IScriptConsole applying a template proposal doesn't work very well (on the first char + // typed it will exit the linked mode and the user will type in the exit location). + // int len = offset - firstCharAbsolutePosition; + // IRegion region = new Region(firstCharAbsolutePosition, len); + // String upToCursor = ps.getDoc().get(firstCharAbsolutePosition, len); + // TemplateContext context = createContext(region, ps.getDoc(), indentPrefs); + // + // Template t = new Template("Assign to local (" + loc + ")", "", "", "${" + loc + "}${cursor} = " + upToCursor, + // false); + // l.add(CompletionProposalFactory.get().createPyTemplateProposal(t, context, region, + // imageCache == null ? null : imageCache.get(UIConstants.COMPLETION_TEMPLATE), + // IPyCompletionProposal.PRIORITY_DEFAULT)); + // + // t = new Template("Assign to field (self." + callName + ")", "", "", + // "self.${" + callName + "}${cursor} = " + upToCursor, + // false); + // l.add(CompletionProposalFactory.get().createPyTemplateProposal(t, context, region, + // imageCache == null ? null : imageCache.get(UIConstants.COMPLETION_TEMPLATE), + // IPyCompletionProposal.PRIORITY_DEFAULT)); + + IImageHandle localImg = getImage(imageCache, UIConstants.ASSIST_ASSIGN_TO_LOCAL); + IImageHandle clsImage = getImage(imageCache, UIConstants.ASSIST_ASSIGN_TO_CLASS); + + l.add(CompletionProposalFactory.get().createAssistAssignCompletionProposal("${" + loc + "} = ", + firstCharAbsolutePosition, 0, 0, localImg, "Assign to local (" + loc + ")", null, null, + IPyCompletionProposal.PRIORITY_DEFAULT, edit)); + + l.add(CompletionProposalFactory.get().createAssistAssignCompletionProposal( + "self.${" + callName + "} = ", + firstCharAbsolutePosition, 0, 5, clsImage, "Assign to field (self." + callName + ")", null, null, + IPyCompletionProposal.PRIORITY_DEFAULT, edit)); return l; } + public static TemplateContext createContext(IRegion region, IDocument document, IIndentPrefs indentPrefs) { + TemplateContextType contextType = new TemplateContextType(); + PyAddTemplateResolvers.addDefaultResolvers(contextType); + return new PyDocumentTemplateContext(contextType, document, region.getOffset(), region.getLength(), "", + indentPrefs); + } + private String changeToCodingStd(String callName) { if (this.std.localsAndAttrsCamelcase()) { return StringUtils.asStyleCamelCaseFirstLower(callName); diff --git a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/surround_with/AssistSurroundWith.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/surround_with/AssistSurroundWith.java index 18c9d900eb..5be1973699 100644 --- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/surround_with/AssistSurroundWith.java +++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/surround_with/AssistSurroundWith.java @@ -17,6 +17,7 @@ import org.eclipse.jface.text.templates.TemplateContext; import org.eclipse.jface.text.templates.TemplateContextType; import org.python.pydev.core.IAssistProps; +import org.python.pydev.core.IIndentPrefs; import org.python.pydev.core.IPyEdit; import org.python.pydev.core.IPythonNature; import org.python.pydev.core.autoedit.DefaultIndentPrefs; @@ -35,12 +36,11 @@ */ public class AssistSurroundWith implements IAssistProps { - protected TemplateContext createContext(IRegion region, IDocument document, IPythonNature nature) { + public static TemplateContext createContext(IRegion region, IDocument document, IIndentPrefs indentPrefs) { TemplateContextType contextType = new TemplateContextType(); PyAddTemplateResolvers.addDefaultResolvers(contextType); return new PyDocumentTemplateContext(contextType, document, region.getOffset(), region.getLength(), "", - DefaultIndentPrefs.get( - nature)); + indentPrefs); } /** @@ -49,13 +49,15 @@ protected TemplateContext createContext(IRegion region, IDocument document, IPyt */ @Override public List getProps(PySelection ps, IImageCache imageCache, File f, - IPythonNature nature, - IPyEdit edit, int offset) throws BadLocationException { + IPythonNature nature, IPyEdit edit, int offset) throws BadLocationException { + + IIndentPrefs indentPrefs = edit != null ? edit.getIndentPrefs() : null; + if (indentPrefs == null) { + indentPrefs = DefaultIndentPrefs.get(nature); + } ArrayList l = new ArrayList(); - String indentation = edit != null ? edit.getIndentPrefs().getIndentationString() - : DefaultIndentPrefs.get( - nature).getIndentationString(); + String indentation = indentPrefs.getIndentationString(); ps.selectCompleteLine(); String selectedText = ps.getSelectedText(); @@ -108,7 +110,7 @@ public List getProps(PySelection ps, IImageCache imag //region IRegion region = ps.getRegion(); - TemplateContext context = createContext(region, ps.getDoc(), nature); + TemplateContext context = createContext(region, ps.getDoc(), indentPrefs); //not static because we need the actual code. String[] replace0to3 = new String[] { startIndent, delimiter, surroundedCode, delimiter, startIndent, diff --git a/plugins/org.python.pydev.ast/src/org/python/pydev/core/templates/PyDocumentTemplateContext.java b/plugins/org.python.pydev.ast/src/org/python/pydev/core/templates/PyDocumentTemplateContext.java index 6592df51d0..292e0e026f 100644 --- a/plugins/org.python.pydev.ast/src/org/python/pydev/core/templates/PyDocumentTemplateContext.java +++ b/plugins/org.python.pydev.ast/src/org/python/pydev/core/templates/PyDocumentTemplateContext.java @@ -11,6 +11,7 @@ import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.eclipse.jface.text.templates.TemplateContextType; import org.python.pydev.core.IGrammarVersionProvider; import org.python.pydev.core.IIndentPrefs; @@ -165,4 +166,18 @@ public static PyDocumentTemplateContext createContext(final TemplateContextType return null; } + public static PyDocumentTemplateContext createContextWithCursor(ISourceViewerForTemplates targetEditor, + IRegion region, String indent) { + TemplateContextType contextType = new TemplateContextType(); + contextType.addResolver(new GlobalTemplateVariables.Cursor()); //We do want the cursor thought. + return createContext(contextType, targetEditor, region, indent); + } + + public static PyDocumentTemplateContext createContextWithDefaultResolvers(ISourceViewerForTemplates edit, + IRegion region, String indentTo) { + TemplateContextType contextType = new TemplateContextType(); + PyAddTemplateResolvers.addDefaultResolvers(contextType); + return createContext(contextType, edit, region, indentTo); + } + } \ No newline at end of file diff --git a/plugins/org.python.pydev/src/org/python/pydev/codingstd/ICodingStd.java b/plugins/org.python.pydev.core/src/org/python/pydev/core/ICodingStd.java similarity index 93% rename from plugins/org.python.pydev/src/org/python/pydev/codingstd/ICodingStd.java rename to plugins/org.python.pydev.core/src/org/python/pydev/core/ICodingStd.java index a7e7eb54f5..d22d314f8a 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/codingstd/ICodingStd.java +++ b/plugins/org.python.pydev.core/src/org/python/pydev/core/ICodingStd.java @@ -4,7 +4,7 @@ * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ -package org.python.pydev.codingstd; +package org.python.pydev.core; public interface ICodingStd { diff --git a/plugins/org.python.pydev.core/src/org/python/pydev/core/preferences/PyDevCodeStylePreferences.java b/plugins/org.python.pydev.core/src/org/python/pydev/core/preferences/PyDevCodeStylePreferences.java new file mode 100644 index 0000000000..66133346bb --- /dev/null +++ b/plugins/org.python.pydev.core/src/org/python/pydev/core/preferences/PyDevCodeStylePreferences.java @@ -0,0 +1,43 @@ +package org.python.pydev.core.preferences; + +import org.python.pydev.shared_core.SharedCorePlugin; + +public class PyDevCodeStylePreferences { + + public static final String USE_LOCALS_AND_ATTRS_CAMELCASE = "USE_LOCALS_AND_ATTRS_CAMELCASE"; + public static final String USE_METHODS_FORMAT = "USE_METHODS_FORMAT"; + public static final boolean DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE = false; + public static final int METHODS_FORMAT_CAMELCASE_FIRST_LOWER = 0; + public static final int METHODS_FORMAT_CAMELCASE_FIRST_UPPER = 1; + public static final int METHODS_FORMAT_UNDERSCORE_SEPARATED = 2; + public static final int DEFAULT_USE_METHODS_FORMAT = METHODS_FORMAT_UNDERSCORE_SEPARATED; + + public static final String[][] LABEL_AND_VALUE = new String[][] { + { "underscore_separated", String.valueOf(METHODS_FORMAT_UNDERSCORE_SEPARATED) }, + { "CamelCase() with first upper", String.valueOf(METHODS_FORMAT_CAMELCASE_FIRST_UPPER) }, + { "camelCase() with first lower", String.valueOf(METHODS_FORMAT_CAMELCASE_FIRST_LOWER) }, }; + + public static final String[][] LOCALS_LABEL_AND_VALUE = new String[][] { + { "underscore_separated", String.valueOf(false) }, + { "camelCase with first lower", String.valueOf(true) }, }; + + public static int TESTING_METHOD_FORMAT = DEFAULT_USE_METHODS_FORMAT; + + public static int useMethodsCamelCase() { + if (SharedCorePlugin.inTestMode()) { + return TESTING_METHOD_FORMAT; + } + return PydevPrefs.getEclipsePreferences().getInt(USE_METHODS_FORMAT, DEFAULT_USE_METHODS_FORMAT); + } + + public static boolean TESTING_METHOD_LOCALS_AND_ATTRS_CAMEL_CASE = DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE; + + public static boolean useLocalsAndAttrsCamelCase() { + if (SharedCorePlugin.inTestMode()) { + return TESTING_METHOD_LOCALS_AND_ATTRS_CAMEL_CASE; + } + return PydevPrefs.getEclipsePreferences().getBoolean(USE_LOCALS_AND_ATTRS_CAMELCASE, + DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE); + } + +} diff --git a/plugins/org.python.pydev.core/src/org/python/pydev/core/proposals/ICompletionProposalFactory.java b/plugins/org.python.pydev.core/src/org/python/pydev/core/proposals/ICompletionProposalFactory.java index 9de5a7f659..1f725835a9 100644 --- a/plugins/org.python.pydev.core/src/org/python/pydev/core/proposals/ICompletionProposalFactory.java +++ b/plugins/org.python.pydev.core/src/org/python/pydev/core/proposals/ICompletionProposalFactory.java @@ -56,8 +56,7 @@ ICompletionProposalHandle createIgnoreCompletionProposal(String replacementStrin ICompletionProposalHandle createAssistAssignCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, IImageHandle image, String displayString, - Object contextInformation, String additionalProposalInfo, int priority, - /*ISourceViewer*/ Object sourceViewer, ICompareContext compareContext); + Object contextInformation, String additionalProposalInfo, int priority, IPyEdit edit); ICompletionProposalHandle createOverrideMethodCompletionProposal(ICompletionRequest request, PySelection ps, int replacementOffset, diff --git a/plugins/org.python.pydev.debug/src_console/org/python/pydev/debug/newconsole/PydevConsoleQuickAssistProcessor.java b/plugins/org.python.pydev.debug/src_console/org/python/pydev/debug/newconsole/PydevConsoleQuickAssistProcessor.java index 5b65f4f667..b50a1f2815 100644 --- a/plugins/org.python.pydev.debug/src_console/org/python/pydev/debug/newconsole/PydevConsoleQuickAssistProcessor.java +++ b/plugins/org.python.pydev.debug/src_console/org/python/pydev/debug/newconsole/PydevConsoleQuickAssistProcessor.java @@ -18,12 +18,12 @@ import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.viewers.ISelection; +import org.python.pydev.ast.assist_assign.AssistAssign; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.log.Log; import org.python.pydev.editor.PySelectionFromEditor; import org.python.pydev.editor.codecompletion.ConvertCompletionProposals; import org.python.pydev.editor.correctionassist.PyCorrectionAssistant; -import org.python.pydev.editor.correctionassist.heuristics.AssistAssign; import org.python.pydev.shared_core.code_completion.ICompletionProposalHandle; import org.python.pydev.shared_interactive_console.console.ui.internal.ScriptConsoleViewer; import org.python.pydev.shared_ui.SharedUiPlugin; @@ -84,8 +84,8 @@ public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationC break; } } - props.addAll(assistAssign.getProps(ps, SharedUiPlugin.getImageCache(), sourceViewer, offset, - commandLine, commandLineOffset)); + props.addAll(assistAssign.getProps(ps, SharedUiPlugin.getImageCache(), null, offset, + commandLine, commandLineOffset, null)); } catch (BadLocationException e) { Log.log(e); diff --git a/plugins/org.python.pydev.refactoring/src/org/python/pydev/refactoring/codegenerator/generateproperties/request/GeneratePropertiesRequest.java b/plugins/org.python.pydev.refactoring/src/org/python/pydev/refactoring/codegenerator/generateproperties/request/GeneratePropertiesRequest.java index ba75ca5e43..81b38a401b 100644 --- a/plugins/org.python.pydev.refactoring/src/org/python/pydev/refactoring/codegenerator/generateproperties/request/GeneratePropertiesRequest.java +++ b/plugins/org.python.pydev.refactoring/src/org/python/pydev/refactoring/codegenerator/generateproperties/request/GeneratePropertiesRequest.java @@ -30,10 +30,10 @@ import org.python.pydev.ast.adapters.IClassDefAdapter; import org.python.pydev.ast.adapters.INodeAdapter; import org.python.pydev.ast.adapters.PropertyTextAdapter; +import org.python.pydev.core.preferences.PyDevCodeStylePreferences; import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.factory.AdapterPrefs; import org.python.pydev.parser.jython.ast.factory.NodeHelper; -import org.python.pydev.plugin.preferences.PyCodeStylePreferencesPage; import org.python.pydev.refactoring.core.request.IRefactoringRequest; import org.python.pydev.shared_core.string.StringUtils; @@ -122,11 +122,11 @@ public String getPropertyName() { */ public static String getAccessorName(String accessType, String attributeName) { accessType += "_" + attributeName; - int useMethodsCamelCase = PyCodeStylePreferencesPage.useMethodsCamelCase(); - if (useMethodsCamelCase == PyCodeStylePreferencesPage.METHODS_FORMAT_CAMELCASE_FIRST_LOWER) { + int useMethodsCamelCase = PyDevCodeStylePreferences.useMethodsCamelCase(); + if (useMethodsCamelCase == PyDevCodeStylePreferences.METHODS_FORMAT_CAMELCASE_FIRST_LOWER) { return StringUtils.asStyleCamelCaseFirstLower(accessType); } - if (useMethodsCamelCase == PyCodeStylePreferencesPage.METHODS_FORMAT_CAMELCASE_FIRST_UPPER) { + if (useMethodsCamelCase == PyDevCodeStylePreferences.METHODS_FORMAT_CAMELCASE_FIRST_UPPER) { return StringUtils.asStyleCamelCaseFirstUpper(accessType); } //default is underscore diff --git a/plugins/org.python.pydev.refactoring/tests/org/python/pydev/refactoring/tests/codegenerator/generateproperties/GeneratePropertiesRequestTest.java b/plugins/org.python.pydev.refactoring/tests/org/python/pydev/refactoring/tests/codegenerator/generateproperties/GeneratePropertiesRequestTest.java index 81e55a94e7..5063e3a544 100644 --- a/plugins/org.python.pydev.refactoring/tests/org/python/pydev/refactoring/tests/codegenerator/generateproperties/GeneratePropertiesRequestTest.java +++ b/plugins/org.python.pydev.refactoring/tests/org/python/pydev/refactoring/tests/codegenerator/generateproperties/GeneratePropertiesRequestTest.java @@ -11,7 +11,7 @@ ******************************************************************************/ package org.python.pydev.refactoring.tests.codegenerator.generateproperties; -import org.python.pydev.plugin.preferences.PyCodeStylePreferencesPage; +import org.python.pydev.core.preferences.PyDevCodeStylePreferences; import org.python.pydev.refactoring.codegenerator.generateproperties.request.GeneratePropertiesRequest; import junit.framework.TestCase; @@ -31,13 +31,13 @@ public static void main(String[] args) { } public void testCodingStd() { - PyCodeStylePreferencesPage.TESTING_METHOD_FORMAT = PyCodeStylePreferencesPage.METHODS_FORMAT_CAMELCASE_FIRST_LOWER; + PyDevCodeStylePreferences.TESTING_METHOD_FORMAT = PyDevCodeStylePreferences.METHODS_FORMAT_CAMELCASE_FIRST_LOWER; assertEquals("delMyAttr", GeneratePropertiesRequest.getAccessorName("del", "my_attr")); - PyCodeStylePreferencesPage.TESTING_METHOD_FORMAT = PyCodeStylePreferencesPage.METHODS_FORMAT_CAMELCASE_FIRST_UPPER; + PyDevCodeStylePreferences.TESTING_METHOD_FORMAT = PyDevCodeStylePreferences.METHODS_FORMAT_CAMELCASE_FIRST_UPPER; assertEquals("DelMyAttr", GeneratePropertiesRequest.getAccessorName("del", "my_attr")); - PyCodeStylePreferencesPage.TESTING_METHOD_FORMAT = PyCodeStylePreferencesPage.METHODS_FORMAT_UNDERSCORE_SEPARATED; + PyDevCodeStylePreferences.TESTING_METHOD_FORMAT = PyDevCodeStylePreferences.METHODS_FORMAT_UNDERSCORE_SEPARATED; assertEquals("del_my_attr", GeneratePropertiesRequest.getAccessorName("del", "my_attr")); } diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/DefaultCompletionProposalFactory.java b/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/DefaultCompletionProposalFactory.java index 485253afc5..2e989e1b02 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/DefaultCompletionProposalFactory.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/DefaultCompletionProposalFactory.java @@ -5,7 +5,6 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateContext; import org.eclipse.swt.widgets.Display; @@ -22,13 +21,13 @@ import org.python.pydev.core.proposals.ICompletionProposalFactory; import org.python.pydev.editor.codecompletion.PyTemplateProposal; import org.python.pydev.editor.codefolding.PyCalltipsContextInformationFromIToken; +import org.python.pydev.editor.correctionassist.AssistAssignCompletionProposal; import org.python.pydev.editor.correctionassist.FixCompletionProposal; import org.python.pydev.editor.correctionassist.IgnoreCompletionProposal; import org.python.pydev.editor.correctionassist.IgnoreCompletionProposalInSameLine; import org.python.pydev.editor.correctionassist.IgnoreFlake8CompletionProposalInSameLine; import org.python.pydev.editor.correctionassist.IgnorePyLintCompletionProposalInSameLine; import org.python.pydev.editor.correctionassist.docstrings.AssistDocstringCompletionProposal; -import org.python.pydev.editor.correctionassist.heuristics.AssistAssignCompletionProposal; import org.python.pydev.shared_core.code_completion.ICompletionProposalHandle; import org.python.pydev.shared_core.code_completion.IPyCompletionProposal.ICompareContext; import org.python.pydev.shared_core.image.IImageHandle; @@ -104,12 +103,10 @@ public ICompletionProposalHandle createIgnoreCompletionProposal(String replaceme @Override public ICompletionProposalHandle createAssistAssignCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, IImageHandle image, String displayString, - Object contextInformation, String additionalProposalInfo, int priority, - Object sourceViewer, ICompareContext compareContext) { + Object contextInformation, String additionalProposalInfo, int priority, IPyEdit edit) { return new AssistAssignCompletionProposal(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, (IContextInformation) contextInformation, additionalProposalInfo, - priority, - (ISourceViewer) sourceViewer, compareContext); + priority); } @Override diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/AssistAssignCompletionProposal.java b/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/AssistAssignCompletionProposal.java new file mode 100644 index 0000000000..4ccb27f1f2 --- /dev/null +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/AssistAssignCompletionProposal.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved. + * Licensed under the terms of the Eclipse Public License (EPL). + * Please see the license.txt included with this distribution for details. + * Any modifications to this file must keep this entire header intact. + */ +package org.python.pydev.editor.correctionassist; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.link.LinkedModeModel; +import org.eclipse.jface.text.link.LinkedModeUI; +import org.eclipse.jface.text.link.LinkedPositionGroup; +import org.eclipse.jface.text.link.ProposalPosition; +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.texteditor.link.EditorLinkedModeUI; +import org.python.pydev.core.interactive_console.IScriptConsoleViewer; +import org.python.pydev.core.log.Log; +import org.python.pydev.editor.codecompletion.proposals.PyCompletionProposal; +import org.python.pydev.shared_core.SharedCorePlugin; +import org.python.pydev.shared_core.image.IImageHandle; +import org.python.pydev.shared_core.string.FastStringBuffer; +import org.python.pydev.shared_ui.utils.RunInUiThread; + +/** + * Proposal for making an assign to a variable or to a field when some method call is found in the current line. + * + * @author Fabio + */ +public class AssistAssignCompletionProposal extends PyCompletionProposal implements ICompletionProposalExtension2 { + + public AssistAssignCompletionProposal(String replacementString, int replacementOffset, int replacementLength, + int cursorPosition, IImageHandle image, String displayString, IContextInformation contextInformation, + String additionalProposalInfo, int priority) { + + super(fixReplacementString(replacementString), replacementOffset, replacementLength, cursorPosition, image, + displayString, + contextInformation, additionalProposalInfo, priority, null); + + } + + private static String fixReplacementString(String replacementString) { + // We receive it in a template format, but that's not what our internal format expects to apply. + return new FastStringBuffer(replacementString, 0).replaceFirst("${", "").replaceFirst("}", "").toString(); + } + + @Override + public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { + if (SharedCorePlugin.inTestMode()) { + return; + } + try { + IDocument document = viewer.getDocument(); + int lineOfOffset = document.getLineOfOffset(fReplacementOffset); + apply(document); + int lineOffset = document.getLineOffset(lineOfOffset); + int lineLength = document.getLineLength(lineOfOffset); + String lineDelimiter = document.getLineDelimiter(lineOfOffset); + int lineDelimiterLen = lineDelimiter != null ? lineDelimiter.length() : 0; + + if (!(viewer instanceof IScriptConsoleViewer)) { + // For the script console we don't apply the linking (only let the selection take place). + LinkedModeModel model = new LinkedModeModel(); + LinkedPositionGroup group = new LinkedPositionGroup(); + //the len-3 is because of the end of the string: " = " because the replacement string is + //something like "xxx = " + + ProposalPosition proposalPosition = new ProposalPosition(document, fReplacementOffset, + fReplacementString.length() - 3, 0, new ICompletionProposal[0]); + group.addPosition(proposalPosition); + + model.addGroup(group); + model.forceInstall(); + final LinkedModeUI ui = new EditorLinkedModeUI(model, viewer); + ui.setExitPosition(viewer, lineOffset + lineLength - lineDelimiterLen, 0, Integer.MAX_VALUE); + Runnable r = new Runnable() { + @Override + public void run() { + ui.enter(); + } + }; + RunInUiThread.async(r); + } + + } catch (BadLocationException e) { + Log.log(e); + } + } + + @Override + public void apply(IDocument document) { + try { + //default apply + document.replace(fReplacementOffset, fReplacementLength, fReplacementString); + } catch (Throwable x) { + // ignore + Log.log(x); + } + } + + @Override + public Point getSelection(IDocument document) { + return new Point(fReplacementOffset, fReplacementString.length() - 3); + } + + @Override + public void selected(ITextViewer viewer, boolean smartToggle) { + } + + @Override + public void unselected(ITextViewer viewer) { + } + + @Override + public boolean validate(IDocument document, int offset, DocumentEvent event) { + return false; + } +} diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/PythonCorrectionProcessor.java b/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/PythonCorrectionProcessor.java index ae4dd9604d..0146210314 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/PythonCorrectionProcessor.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/PythonCorrectionProcessor.java @@ -28,6 +28,7 @@ import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; import org.eclipse.ui.texteditor.spelling.SpellingCorrectionProcessor; import org.eclipse.ui.texteditor.spelling.SpellingProblem; +import org.python.pydev.ast.assist_assign.AssistAssign; import org.python.pydev.ast.codecompletion.ProposalsComparator; import org.python.pydev.ast.surround_with.AssistSurroundWith; import org.python.pydev.core.ExtensionHelper; @@ -40,7 +41,6 @@ import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.log.Log; import org.python.pydev.editor.PyEdit; -import org.python.pydev.editor.correctionassist.heuristics.AssistAssign; import org.python.pydev.editor.correctionassist.heuristics.AssistImport; import org.python.pydev.editor.correctionassist.heuristics.AssistImportToLocal; import org.python.pydev.editor.correctionassist.heuristics.AssistPercentToFormat; diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistAssignCompletionProposal.java b/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistAssignCompletionProposal.java deleted file mode 100644 index a496e9d82c..0000000000 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistAssignCompletionProposal.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved. - * Licensed under the terms of the Eclipse Public License (EPL). - * Please see the license.txt included with this distribution for details. - * Any modifications to this file must keep this entire header intact. - */ -package org.python.pydev.editor.correctionassist.heuristics; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.link.LinkedModeModel; -import org.eclipse.jface.text.link.LinkedModeUI; -import org.eclipse.jface.text.link.LinkedPositionGroup; -import org.eclipse.jface.text.link.ProposalPosition; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.swt.graphics.Point; -import org.eclipse.ui.texteditor.link.EditorLinkedModeUI; -import org.python.pydev.core.log.Log; -import org.python.pydev.editor.codecompletion.proposals.PyCompletionProposal; -import org.python.pydev.shared_core.SharedCorePlugin; -import org.python.pydev.shared_core.image.IImageHandle; -import org.python.pydev.shared_ui.utils.RunInUiThread; - -/** - * Proposal for making an assign to a variable or to a field when some method call is found in the current line. - * - * @author Fabio - */ -public class AssistAssignCompletionProposal extends PyCompletionProposal { - - /** - * The related viewer (needed to get into link mode) - */ - private ISourceViewer sourceViewer; - - public AssistAssignCompletionProposal(String replacementString, int replacementOffset, int replacementLength, - int cursorPosition, IImageHandle image, String displayString, IContextInformation contextInformation, - String additionalProposalInfo, int priority, ISourceViewer sourceViewer, ICompareContext compareContext) { - - super(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, - contextInformation, additionalProposalInfo, priority, compareContext); - this.sourceViewer = sourceViewer; - - } - - @Override - public void apply(IDocument document) { - try { - //default apply - int lineOfOffset = document.getLineOfOffset(fReplacementOffset); - document.replace(fReplacementOffset, fReplacementLength, fReplacementString); - - if (SharedCorePlugin.inTestMode()) { - return; - } - int lineOffset = document.getLineOffset(lineOfOffset); - int lineLength = document.getLineLength(lineOfOffset); - String lineDelimiter = document.getLineDelimiter(lineOfOffset); - int lineDelimiterLen = lineDelimiter != null ? lineDelimiter.length() : 0; - - ISourceViewer viewer = sourceViewer; - - LinkedModeModel model = new LinkedModeModel(); - LinkedPositionGroup group = new LinkedPositionGroup(); - - //the len-3 is because of the end of the string: " = " because the replacement string is - //something like "xxx = " - ProposalPosition proposalPosition = new ProposalPosition(document, fReplacementOffset, - fReplacementString.length() - 3, 0, new ICompletionProposal[0]); - group.addPosition(proposalPosition); - - model.addGroup(group); - model.forceInstall(); - - final LinkedModeUI ui = new EditorLinkedModeUI(model, viewer); - ui.setExitPosition(viewer, lineOffset + lineLength - lineDelimiterLen, 0, Integer.MAX_VALUE); - Runnable r = new Runnable() { - @Override - public void run() { - ui.enter(); - } - }; - RunInUiThread.async(r); - - } catch (Throwable x) { - // ignore - Log.log(x); - } - } - - @Override - public Point getSelection(IDocument document) { - return null; - } -} diff --git a/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PyCodeStylePreferencesPage.java b/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PyCodeStylePreferencesPage.java index cd937064b3..9cb98b23c7 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PyCodeStylePreferencesPage.java +++ b/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PyCodeStylePreferencesPage.java @@ -14,33 +14,11 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; -import org.python.pydev.core.preferences.PydevPrefs; +import org.python.pydev.core.preferences.PyDevCodeStylePreferences; import org.python.pydev.plugin.PydevPlugin; -import org.python.pydev.shared_core.SharedCorePlugin; public class PyCodeStylePreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { - public static final String USE_LOCALS_AND_ATTRS_CAMELCASE = "USE_LOCALS_AND_ATTRS_CAMELCASE"; - - public static final String USE_METHODS_FORMAT = "USE_METHODS_FORMAT"; - - public static final boolean DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE = false; - - public static final int METHODS_FORMAT_CAMELCASE_FIRST_LOWER = 0; - public static final int METHODS_FORMAT_CAMELCASE_FIRST_UPPER = 1; - public static final int METHODS_FORMAT_UNDERSCORE_SEPARATED = 2; - - public static final int DEFAULT_USE_METHODS_FORMAT = METHODS_FORMAT_UNDERSCORE_SEPARATED; - - public static final String[][] LABEL_AND_VALUE = new String[][] { - { "underscore_separated", String.valueOf(METHODS_FORMAT_UNDERSCORE_SEPARATED) }, - { "CamelCase() with first upper", String.valueOf(METHODS_FORMAT_CAMELCASE_FIRST_UPPER) }, - { "camelCase() with first lower", String.valueOf(METHODS_FORMAT_CAMELCASE_FIRST_LOWER) }, }; - - public static final String[][] LOCALS_LABEL_AND_VALUE = new String[][] { - { "underscore_separated", String.valueOf(false) }, - { "camelCase with first lower", String.valueOf(true) }, }; - private Label labelLocalsFormat; private Label labelMethodsFormat; @@ -59,19 +37,19 @@ public PyCodeStylePreferencesPage() { public void createFieldEditors() { Composite p = getFieldEditorParent(); - useLocalsAndAttrsCamelCase = new RadioGroupFieldEditor(USE_LOCALS_AND_ATTRS_CAMELCASE, - "Locals and attributes format (used for assign quick-assist)?", 1, LOCALS_LABEL_AND_VALUE, p, true); + useLocalsAndAttrsCamelCase = new RadioGroupFieldEditor(PyDevCodeStylePreferences.USE_LOCALS_AND_ATTRS_CAMELCASE, + "Locals and attributes format (used for assign quick-assist)?", 1, PyDevCodeStylePreferences.LOCALS_LABEL_AND_VALUE, p, true); addField(useLocalsAndAttrsCamelCase); - useMethodsFormat = new RadioGroupFieldEditor(USE_METHODS_FORMAT, - "Methods format (used for generate properties refactoring)", 1, LABEL_AND_VALUE, p, true); + useMethodsFormat = new RadioGroupFieldEditor(PyDevCodeStylePreferences.USE_METHODS_FORMAT, + "Methods format (used for generate properties refactoring)", 1, PyDevCodeStylePreferences.LABEL_AND_VALUE, p, true); addField(useMethodsFormat); labelLocalsFormat = new Label(p, SWT.NONE); labelMethodsFormat = new Label(p, SWT.NONE); - updateLabelLocalsAndAttrs(useLocalsAndAttrsCamelCase()); - updateLabelMethods(useMethodsCamelCase()); + updateLabelLocalsAndAttrs(PyDevCodeStylePreferences.useLocalsAndAttrsCamelCase()); + updateLabelMethods(PyDevCodeStylePreferences.useMethodsCamelCase()); } @@ -80,10 +58,10 @@ public void createFieldEditors() { */ private void updateLabelMethods(int useMethodsFormat) { - if (useMethodsFormat == METHODS_FORMAT_CAMELCASE_FIRST_UPPER) { + if (useMethodsFormat == PyDevCodeStylePreferences.METHODS_FORMAT_CAMELCASE_FIRST_UPPER) { labelMethodsFormat.setText("Refactoring property methods in the format def MyMethod() "); - } else if (useMethodsFormat == METHODS_FORMAT_UNDERSCORE_SEPARATED) { + } else if (useMethodsFormat == PyDevCodeStylePreferences.METHODS_FORMAT_UNDERSCORE_SEPARATED) { labelMethodsFormat.setText("Refactoring property methods in the format def my_method() "); } else { @@ -107,25 +85,6 @@ private void updateLabelLocalsAndAttrs(boolean useCamelCase) { public void init(IWorkbench workbench) { } - public static int TESTING_METHOD_FORMAT = DEFAULT_USE_METHODS_FORMAT; - - public static int useMethodsCamelCase() { - if (SharedCorePlugin.inTestMode()) { - return TESTING_METHOD_FORMAT; - } - return PydevPrefs.getEclipsePreferences().getInt(USE_METHODS_FORMAT, DEFAULT_USE_METHODS_FORMAT); - } - - public static boolean TESTING_METHOD_LOCALS_AND_ATTRS_CAMEL_CASE = DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE; - - public static boolean useLocalsAndAttrsCamelCase() { - if (SharedCorePlugin.inTestMode()) { - return TESTING_METHOD_LOCALS_AND_ATTRS_CAMEL_CASE; - } - return PydevPrefs.getEclipsePreferences().getBoolean(USE_LOCALS_AND_ATTRS_CAMELCASE, - DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE); - } - @Override public void propertyChange(PropertyChangeEvent event) { super.propertyChange(event); @@ -140,7 +99,7 @@ public void propertyChange(PropertyChangeEvent event) { String newValue = (String) event.getNewValue(); val = Integer.parseInt(newValue); } catch (NumberFormatException e) { - val = DEFAULT_USE_METHODS_FORMAT; + val = PyDevCodeStylePreferences.DEFAULT_USE_METHODS_FORMAT; } updateLabelMethods(val); diff --git a/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java b/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java index 4fc02ceda8..6bace53f07 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java +++ b/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java @@ -16,6 +16,7 @@ import org.python.pydev.builder.todo.PyTodoPrefPage; import org.python.pydev.core.docstrings.DocstringPreferences; import org.python.pydev.core.imports.ImportPreferences; +import org.python.pydev.core.preferences.PyDevCodeStylePreferences; import org.python.pydev.editor.codefolding.PyDevCodeFoldingPrefPage; import org.python.pydev.editor.commentblocks.CommentBlocksPreferences; import org.python.pydev.editor.hover.PyHoverPreferencesPage; @@ -220,10 +221,10 @@ public void initializeDefaultPreferences() { //[[[end]]] //coding style - node.putBoolean(PyCodeStylePreferencesPage.USE_LOCALS_AND_ATTRS_CAMELCASE, - PyCodeStylePreferencesPage.DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE); - node.putInt(PyCodeStylePreferencesPage.USE_METHODS_FORMAT, - PyCodeStylePreferencesPage.DEFAULT_USE_METHODS_FORMAT); + node.putBoolean(PyDevCodeStylePreferences.USE_LOCALS_AND_ATTRS_CAMELCASE, + PyDevCodeStylePreferences.DEFAULT_USE_LOCALS_AND_ATTRS_CAMELCASE); + node.putInt(PyDevCodeStylePreferences.USE_METHODS_FORMAT, + PyDevCodeStylePreferences.DEFAULT_USE_METHODS_FORMAT); //Editor title node.putBoolean(PyTitlePreferencesPage.TITLE_EDITOR_NAMES_UNIQUE, diff --git a/plugins/org.python.pydev/tests/org/python/pydev/editor/correctionassist/heuristics/AssistAssignTest.java b/plugins/org.python.pydev/tests/org/python/pydev/editor/correctionassist/heuristics/AssistAssignTest.java index fd7a0698c8..65970e8b61 100644 --- a/plugins/org.python.pydev/tests/org/python/pydev/editor/correctionassist/heuristics/AssistAssignTest.java +++ b/plugins/org.python.pydev/tests/org/python/pydev/editor/correctionassist/heuristics/AssistAssignTest.java @@ -15,7 +15,8 @@ import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; -import org.python.pydev.codingstd.ICodingStd; +import org.python.pydev.ast.assist_assign.AssistAssign; +import org.python.pydev.core.ICodingStd; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.proposals.CompletionProposalFactory; import org.python.pydev.editor.codecompletion.proposals.DefaultCompletionProposalFactory;