diff --git a/plugins/org.python.pydev.jython/jysrc/pytemplate_defaults.py b/plugins/org.python.pydev.jython/jysrc/pytemplate_defaults.py index 4cecaab1b7..66530b4758 100644 --- a/plugins/org.python.pydev.jython/jysrc/pytemplate_defaults.py +++ b/plugins/org.python.pydev.jython/jysrc/pytemplate_defaults.py @@ -57,18 +57,22 @@ def _IsGrammar3(context): # ISO-8601 Dates #=============================================================================== def GetISODate(context): + # Migrated to java return time.strftime("%Y-%m-%d") def GetISODateString1(context): + # Migrated to java return time.strftime("%Y-%m-%d %H:%M") def GetISODateString2(context): + # Migrated to java return time.strftime("%Y-%m-%d %H:%M:%S") #=================================================================================================== # GetModuleName #=================================================================================================== def GetModuleName(context): + # Migrated to java return context.getModuleName() @@ -79,6 +83,7 @@ def _GetCurrentASTPath(context, reverse=False): ''' @return: ArrayList(SimpleNode) ''' + # Migrated to java FastParser = context.getFastParserClass() # from org.python.pydev.parser.fastparser import FastParser selection = _CreateSelection(context) ret = FastParser.parseToKnowGloballyAccessiblePath( @@ -94,6 +99,7 @@ def _GetCurrentASTPath(context, reverse=False): # GetQualifiedNameScope #=================================================================================================== def GetQualifiedNameScope(context): + # Migrated to java NodeUtils = context.getNodeUtilsClass() # from org.python.pydev.parser.visitors import NodeUtils ret = '' @@ -108,6 +114,7 @@ def GetQualifiedNameScope(context): # _GetCurrentClassStmt #=================================================================================================== def _GetCurrentClassStmt(context): + # Migrated to java NodeUtils = context.getNodeUtilsClass() #from org.python.pydev.parser.visitors import NodeUtils ClassDef = context.getClassDefClass() # from org.python.pydev.parser.jython.ast import ClassDef @@ -116,11 +123,11 @@ def _GetCurrentClassStmt(context): return stmt return None - #=================================================================================================== # GetCurrentClass #=================================================================================================== def GetCurrentClass(context): + # Migrated to java NodeUtils = context.getNodeUtilsClass() #from org.python.pydev.parser.visitors import NodeUtils ClassDef = context.getClassDefClass() # from org.python.pydev.parser.jython.ast import ClassDef @@ -130,14 +137,11 @@ def GetCurrentClass(context): return '' - -template_helper.AddTemplateVariable(py_context_type, 'current_class', 'Current class', GetCurrentClass) - - #=================================================================================================== # GetSelfOrCls #=================================================================================================== def GetSelfOrCls(context): + # Migrated to java FunctionDef = context.getFunctionDefClass() # from org.python.pydev.parser.jython.ast import ClassDef FastParser = context.getFastParserClass() # from org.python.pydev.parser.fastparser import FastParser @@ -151,36 +155,28 @@ def GetSelfOrCls(context): return 'self' -template_helper.AddTemplateVariable(py_context_type, 'self_or_cls', 'Get `self` or `cls`', GetSelfOrCls) - - #=================================================================================================== # GetPydevdFileLocation #=================================================================================================== def GetPydevdFileLocation(context): + # Migrated to java from org.python.pydev.debug.ui.launching import PythonRunnerConfig # @UnresolvedImport return PythonRunnerConfig.getDebugScript() -template_helper.AddTemplateVariable( - py_context_type, 'pydevd_file_location', 'pydevd.py File Location', GetPydevdFileLocation) - #=================================================================================================== # GetPydevdDirLocation #=================================================================================================== def GetPydevdDirLocation(context): + # Migrated to java from org.python.pydev.debug.ui.launching import PythonRunnerConfig # @UnresolvedImport import os return os.path.split(PythonRunnerConfig.getDebugScript())[0] -template_helper.AddTemplateVariable( - py_context_type, 'pydevd_dir_location', 'pydevd.py Directory Location', GetPydevdDirLocation) - - - #=================================================================================================== # GetCurrentMethod #=================================================================================================== def GetCurrentMethod(context): + # Migrated to java NodeUtils = context.getNodeUtilsClass() #from org.python.pydev.parser.visitors import NodeUtils FunctionDef = context.getFunctionDefClass() # from org.python.pydev.parser.jython.ast import FunctionDef @@ -189,15 +185,11 @@ def GetCurrentMethod(context): return NodeUtils.getRepresentationString(stmt) return '' - - -template_helper.AddTemplateVariable(py_context_type, 'current_method', 'Current method', GetCurrentMethod) - - #=================================================================================================== # _GetPreviousOrNextClassOrMethod #=================================================================================================== def _GetPreviousOrNextClassOrMethod(context, searchForward): + # Migrated to java NodeUtils = context.getNodeUtilsClass() #from org.python.pydev.parser.visitors import NodeUtils FastParser = context.getFastParserClass() #from org.python.pydev.parser.fastparser import FastParser doc = context.getDocument() @@ -215,26 +207,22 @@ def _GetPreviousOrNextClassOrMethod(context, searchForward): # GetPreviousClassOrMethod #=================================================================================================== def GetPreviousClassOrMethod(context): + # Migrated to java return _GetPreviousOrNextClassOrMethod(context, False) -template_helper.AddTemplateVariable( - py_context_type, 'prev_class_or_method', 'Previous class or method', GetPreviousClassOrMethod) - #=================================================================================================== # GetNextClassOrMethod #=================================================================================================== def GetNextClassOrMethod(context): + # Migrated to java return _GetPreviousOrNextClassOrMethod(context, True) -template_helper.AddTemplateVariable( - py_context_type, 'next_class_or_method', 'Next class or method', GetNextClassOrMethod) - - - #=================================================================================================== # GetSuperclass #=================================================================================================== def GetSuperclass(context): + # Migrated to java + selection = _CreateSelection(context) stmt = _GetCurrentClassStmt(context) BadLocationException = context.getBadLocationExceptionClass() # from org.eclipse.jface.text import BadLocationException @@ -283,6 +271,3 @@ def GetSuperclass(context): return contents.strip() return '' - -template_helper.AddTemplateVariable( - py_context_type, 'superclass', 'Superclass of the current class', GetSuperclass) diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyContextType.java b/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyContextType.java index 90d91a392e..883049c060 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyContextType.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyContextType.java @@ -62,6 +62,14 @@ private void addGlobalResolvers() { addResolver(PyTemplatesDefault.IsoDate2()); addResolver(PyTemplatesDefault.ModuleName()); addResolver(PyTemplatesDefault.QualifiedNameScope()); + addResolver(PyTemplatesDefault.CurrentClass()); + addResolver(PyTemplatesDefault.SelfOrCls()); + addResolver(PyTemplatesDefault.PydevdFileLocation()); + addResolver(PyTemplatesDefault.PydevdDirLocation()); + addResolver(PyTemplatesDefault.CurrentMethod()); + addResolver(PyTemplatesDefault.PreviousClassOrMethod()); + addResolver(PyTemplatesDefault.NextClassOrMethod()); + addResolver(PyTemplatesDefault.Superclass()); PyContextTypeVariables.addResolvers(this); HashMap locals = new HashMap(); diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyTemplatesDefault.java b/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyTemplatesDefault.java index 35e2e3b1e4..d4c73b68b1 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyTemplatesDefault.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/templates/PyTemplatesDefault.java @@ -1,38 +1,58 @@ package org.python.pydev.editor.templates; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.templates.TemplateContext; +import org.eclipse.jface.text.templates.TemplateVariableResolver; +import org.python.pydev.core.CorePlugin; import org.python.pydev.core.docutils.PySelection; +import org.python.pydev.core.log.Log; import org.python.pydev.editor.codecompletion.templates.PyDocumentTemplateContext; import org.python.pydev.parser.fastparser.FastParser; +import org.python.pydev.parser.jython.ast.ClassDef; +import org.python.pydev.parser.jython.ast.FunctionDef; +import org.python.pydev.parser.jython.ast.NameTok; import org.python.pydev.parser.jython.ast.stmtType; import org.python.pydev.parser.visitors.NodeUtils; import org.python.pydev.shared_core.callbacks.ICallback; +import org.python.pydev.shared_core.io.FileUtils; import org.python.pydev.shared_core.string.FastStringBuffer; public class PyTemplatesDefault { public static class CallableTemplateVariableResolver extends PyTemplateVariableResolver { - private ICallback callable; + private ICallback*/, PyDocumentTemplateContext> callable; public CallableTemplateVariableResolver(String type, String description, - ICallback callable) { + ICallback*/, PyDocumentTemplateContext> callable) { super(type, description); this.callable = callable; } @Override public String[] resolveAll(TemplateContext context) { - String ret = this.callable.call((PyDocumentTemplateContext) context); - if (ret == null) { + Object obj = this.callable.call((PyDocumentTemplateContext) context); + if (obj == null) { return new String[0]; } - return new String[] { ret }; + if (obj instanceof String) { + String ret = (String) obj; + return new String[] { ret }; + } + if (obj instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) obj; + return list.toArray(new String[0]); + } + throw new RuntimeException("Error. Expected String or List. Found: " + obj); } } @@ -102,4 +122,169 @@ public static CallableTemplateVariableResolver QualifiedNameScope() { }); } + public static ClassDef getCurrentClassStmt(PyDocumentTemplateContext context) { + for (stmtType stmt : getCurrentAstPath(context, true)) { + if (stmt instanceof ClassDef) { + return (ClassDef) stmt; + } + } + return null; + } + + public static CallableTemplateVariableResolver CurrentClass() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("current_class", + "Current class", + (context) -> { + stmtType stmt = getCurrentClassStmt(context); + if (stmt != null) { + return NodeUtils.getRepresentationString(stmt); + } + + return ""; + }); + } + + public static CallableTemplateVariableResolver SelfOrCls() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("self_or_cls", + "Get `self` or `cls`", + (context) -> { + PySelection selection = context.createPySelection(); + stmtType node = FastParser.firstClassOrFunction(context.getDocument(), + selection.getStartLineIndex(), false, false); + if (node instanceof FunctionDef) { + String firstToken = selection.getFirstInsideParentesisTok(node.beginLine - 1); + if ("cls".equals(firstToken)) { + return "cls"; + } + } + + return "self"; + }); + } + + public static TemplateVariableResolver PydevdFileLocation() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("pydevd_file_location", + "pydevd.py File Location", + (context) -> { + + try { + return FileUtils.getFileAbsolutePath(CorePlugin.getScriptWithinPySrc("pydevd.py")); + } catch (CoreException e) { + Log.log(e); + return ""; + } + }); + } + + public static TemplateVariableResolver PydevdDirLocation() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("pydevd_dir_location", + "pydevd.py Directory Location", + (context) -> { + + try { + return FileUtils + .getFileAbsolutePath(CorePlugin.getScriptWithinPySrc("pydevd.py").getParentFile()); + } catch (CoreException e) { + Log.log(e); + return ""; + } + }); + } + + public static TemplateVariableResolver CurrentMethod() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("current_method", + "Current method", + (context) -> { + for (stmtType stmt : getCurrentAstPath(context, true)) { + if (stmt instanceof FunctionDef) { + return NodeUtils.getRepresentationString(stmt); + } + } + return ""; + }); + } + + private static String getPreviousOrNextClassOrMethod(PyDocumentTemplateContext context, boolean searchForward) { + IDocument doc = context.getDocument(); + PySelection selection = context.createPySelection(); + int startLine = selection.getStartLineIndex(); + stmtType found = FastParser.firstClassOrFunction(doc, startLine, searchForward, context.isCythonFile()); + if (found != null) { + return NodeUtils.getRepresentationString(found); + } + return ""; + } + + public static TemplateVariableResolver PreviousClassOrMethod() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("prev_class_or_method", + "Previous class or method", + (context) -> { + return getPreviousOrNextClassOrMethod(context, false); + }); + } + + public static TemplateVariableResolver NextClassOrMethod() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("next_class_or_method", + "Next class or method", + (context) -> { + return getPreviousOrNextClassOrMethod(context, true); + }); + } + + public static TemplateVariableResolver Superclass() { + return new PyTemplatesDefault.CallableTemplateVariableResolver("superclass", + "Superclass of the current class", + (context) -> { + PySelection selection = context.createPySelection(); + ClassDef stmt = getCurrentClassStmt(context); + if (stmt == null) { + return ""; + } + + IDocument doc = context.getDocument(); + NameTok name = (NameTok) stmt.name; + int nameStartOffset = selection.getAbsoluteCursorOffset(name.beginLine - 1, name.beginColumn - 1); + nameStartOffset += name.id.length(); + + boolean foundStart = false; + int i = 0; + FastStringBuffer contents = new FastStringBuffer(); + while (true) { + try { + char c = doc.get(nameStartOffset + i, 1).charAt(0); + i++; + + if (c == '(') { + foundStart = true; + } else if (c == ')' || c == ':') { + break; + } else if (c == '\r' || c == '\n' || c == ' ' || c == '\t') { + // pass + } else if (c == '#') { // Skip comments + while (c != '\r' && c != '\n') { + c = doc.get(nameStartOffset + i, 1).charAt(0); + i++; + } + } else { + if (foundStart) { + contents.append(c); + } + } + } catch (BadLocationException e) { + return ""; // Seems the class declaration is not properly finished as we're now out of bounds in the doc. + } + } + + if (contents.indexOf(',') != -1) { + List ret = new ArrayList<>(); + for (String param : contents.toString().split(",")) { + ret.add(param.trim()); + } + return ret; + } + + return contents.toString().trim(); + }); + } + }