/** * Copyright (c) 2005-2011 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.codecompletion; import java.io.IOException; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.python.pydev.core.IGrammarVersionProvider; import org.python.pydev.core.IIndentPrefs; import org.python.pydev.core.MisconfigurationException; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.StringUtils; import org.python.pydev.core.log.Log; import org.python.pydev.editor.PyEdit; import org.python.pydev.editor.autoedit.DefaultIndentPrefs; import org.python.pydev.editor.codefolding.PySourceViewer; import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.FunctionDef; import org.python.pydev.parser.jython.ast.NameTok; import org.python.pydev.parser.jython.ast.Pass; import org.python.pydev.parser.jython.ast.stmtType; import org.python.pydev.parser.jython.ast.factory.AdapterPrefs; import org.python.pydev.parser.jython.ast.factory.PyAstFactory; import org.python.pydev.parser.prettyprinterv2.MakeAstValidForPrettyPrintingVisitor; import org.python.pydev.parser.prettyprinterv2.PrettyPrinterPrefsV2; import org.python.pydev.parser.prettyprinterv2.PrettyPrinterV2; /** * @author fabioz * */ public class OverrideMethodCompletionProposal extends AbstractPyCompletionProposalExtension2 { private final FunctionDef functionDef; private final String parentClassName; private String currentClassName; public OverrideMethodCompletionProposal(int replacementOffset, int replacementLength, int cursorPosition, Image image, FunctionDef functionDef, String parentClassName, String currentClassName) { super("", replacementOffset, replacementLength, cursorPosition, IPyCompletionProposal.PRIORITY_CREATE); this.fImage = image; this.functionDef = functionDef; this.fDisplayString = ((NameTok) functionDef.name).id + " (Override method in " + parentClassName + ")"; this.parentClassName = parentClassName; this.currentClassName = currentClassName; } /* (non-Javadoc) * @see org.python.pydev.editor.codecompletion.PyCompletionProposal#apply(org.eclipse.jface.text.IDocument) */ @Override public void apply(IDocument document) { } /* (non-Javadoc) * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int) */ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { IDocument document = viewer.getDocument(); int finalOffset = applyOnDocument(viewer, document, trigger, stateMask, offset); if (finalOffset >= 0) { try { PySelection ps = new PySelection(document, finalOffset); int firstCharPosition = PySelection.getFirstCharPosition(ps.getLine()); int lineOffset = ps.getLineOffset(); int location = lineOffset + firstCharPosition; int len = finalOffset - location; fCursorPosition = location; fReplacementLength = len; } catch (Exception e) { Log.log(e); } } } public int applyOnDocument(ITextViewer viewer, IDocument document, char trigger, int stateMask, int offset) { IGrammarVersionProvider versionProvider = null; PyEdit edit = null; if (viewer instanceof PySourceViewer) { PySourceViewer pySourceViewer = (PySourceViewer) viewer; versionProvider = edit = pySourceViewer.getEdit(); } else { versionProvider = new IGrammarVersionProvider() { public int getGrammarVersion() throws MisconfigurationException { return IGrammarVersionProvider.LATEST_GRAMMAR_VERSION; } }; } String delimiter = PySelection.getDelimiter(document); PyAstFactory factory = new PyAstFactory(new AdapterPrefs(delimiter, versionProvider)); stmtType overrideBody = factory.createOverrideBody(this.functionDef, parentClassName, currentClassName); //Note that the copy won't have a parent. FunctionDef functionDef = this.functionDef.createCopy(false); functionDef.body = new stmtType[] { overrideBody != null ? overrideBody : new Pass() }; try { MakeAstValidForPrettyPrintingVisitor.makeValid(functionDef); } catch (Exception e) { Log.log(e); } String printed = printAst(edit, functionDef, delimiter); PySelection ps = new PySelection(document, offset); try { String lineContentsToCursor = ps.getLineContentsToCursor(); int defIndex = lineContentsToCursor.indexOf("def"); int defOffset = ps.getLineOffset() + defIndex; printed = StringUtils.indentTo(printed, lineContentsToCursor.substring(0, defIndex), false); printed = StringUtils.rightTrim(printed); this.fLen += offset - defOffset; document.replace(defOffset, this.fLen, printed); return defOffset + printed.length(); } catch (BadLocationException x) { // ignore } return -1; } public static String printAst(PyEdit edit, SimpleNode astToPrint, String lineDelimiter) { String str = null; if (astToPrint != null) { IIndentPrefs indentPrefs; if (edit != null) { indentPrefs = edit.getIndentPrefs(); } else { indentPrefs = DefaultIndentPrefs.get(); } PrettyPrinterPrefsV2 prefsV2 = PrettyPrinterV2.createDefaultPrefs(edit, indentPrefs, lineDelimiter); PrettyPrinterV2 prettyPrinterV2 = new PrettyPrinterV2(prefsV2); try { str = prettyPrinterV2.print(astToPrint); } catch (IOException e) { Log.log(e); } } return str; } /* (non-Javadoc) * @see org.python.pydev.editor.codecompletion.AbstractPyCompletionProposalExtension2#getTriggerCharacters() */ @Override public char[] getTriggerCharacters() { return null; } @Override public Point getSelection(IDocument document) { return new Point(fCursorPosition, fReplacementLength); } }