@Override protected SourceViewerConfiguration createSourceViewerConfiguration() { PyContentAssistant contentAssist = new PyContentAssistant(); IContentAssistProcessor processor = createConsoleCompletionProcessor(contentAssist); contentAssist.setContentAssistProcessor( processor, JSScriptConsoleSourceViewerConfiguration.PARTITION_TYPE); contentAssist.enableAutoActivation(true); contentAssist.enableAutoInsert(false); contentAssist.setAutoActivationDelay(PyCodeCompletionPreferencesPage.getAutocompleteDelay()); PyCorrectionAssistant quickAssist = new PyCorrectionAssistant(); // next create a content assistant processor to populate the completions window IQuickAssistProcessor quickAssistProcessor = createConsoleQuickAssistProcessor(quickAssist); // Correction assist works on all quickAssist.setQuickAssistProcessor(quickAssistProcessor); SourceViewerConfiguration cfg = new JSScriptConsoleSourceViewerConfiguration(createHover(), contentAssist, quickAssist); return cfg; }
/** * This method creates the python server process and starts the sockets, so that we can talk with * the server. * * @param milisSleep: time to wait after creating the process. * @throws IOException is some error happens creating the sockets - the process is terminated. * @throws JDTNotAvailableException * @throws CoreException * @throws CoreException * @throws MisconfigurationException */ /*package*/ void startIt(IInterpreterInfo interpreter) throws IOException, JDTNotAvailableException, CoreException, MisconfigurationException { int milisSleep = AbstractShell.DEFAULT_SLEEP_BETWEEN_ATTEMPTS; synchronized (ioLock) { this.shellInterpreter = interpreter; if (inStart || isConnected) { // it is already in the process of starting, so, if we are in another thread, just forget // about it. return; } inStart = true; try { if (finishedForGood) { throw new RuntimeException( "Shells are already finished for good, so, it is an invalid state to try to restart it."); } ProcessCreationInfo processInfo = null; try { serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.bind(new InetSocketAddress(0)); serverSocket = serverSocketChannel.socket(); int port = serverSocket.getLocalPort(); SocketUtil.checkValidPort(port); if (process != null) { endIt(); // end the current process } processInfo = createServerProcess(interpreter, port); dbg("executed: " + processInfo.getProcessLog(), 1); sleepALittle(200); // Give it some time to warmup. if (process == null) { String msg = "Error creating python process - got null process.\n" + processInfo.getProcessLog(); dbg(msg, 1); Log.log(msg); throw new CoreException(PydevPlugin.makeStatus(IStatus.ERROR, msg, new Exception(msg))); } try { int exitVal = process .exitValue(); // should throw exception saying that it still is not // terminated... String msg = "Error creating python process - exited before creating sockets - exitValue = (" + exitVal + ").\n" + processInfo.getProcessLog(); dbg(msg, 1); Log.log(msg); throw new CoreException(PydevPlugin.makeStatus(IStatus.ERROR, msg, new Exception(msg))); } catch (IllegalThreadStateException e2) { // this is ok } dbg("afterCreateProcess ", 1); // ok, process validated, so, let's get its output and store it for further use. boolean connected = false; int attempt = 0; dbg("connecting... ", 1); sleepALittle(milisSleep); int maxAttempts = PyCodeCompletionPreferencesPage.getNumberOfConnectionAttempts(); dbg("maxAttempts: " + maxAttempts, 1); dbg("finishedForGood: " + finishedForGood, 1); while (!connected && attempt < maxAttempts && !finishedForGood) { attempt += 1; dbg("connecting attept..." + attempt, 1); try { try { dbg("serverSocket.accept()! ", 1); long initial = System.currentTimeMillis(); SocketChannel accept = null; while (accept == null && System.currentTimeMillis() - initial < 5000) { // Each attempt is 5 seconds... dbg( "serverSocketChannel.accept(): waiting for python client to connect back to the eclipse java vm", 1); accept = serverSocketChannel.accept(); if (accept == null) { sleepALittle(500); } } if (accept != null) { socket = accept.socket(); dbg("socketToRead.setSoTimeout(5000) ", 1); socket.setSoTimeout(5000); // let's give it a higher timeout connected = true; dbg("connected! ", 1); } else { String msg = "The python client still hasn't connected back to the eclipse java vm (will retry...)"; dbg(msg, 1); Log.log(msg); } } catch (SocketTimeoutException e) { // that's ok, timeout for waiting connection expired, let's check it again in the // next loop dbg("SocketTimeoutException! ", 1); } } catch (IOException e1) { dbg("IOException! ", 1); } // if not connected, let's sleep a little for another attempt if (!connected) { if (attempt > 1) { // Don't log first failed attempt. String msg = "Attempt: " + attempt + " of " + maxAttempts + " failed, trying again...(socket connected: " + (socket == null ? "still null" : socket.isConnected()) + ")"; dbg(msg, 1); Log.log(msg); sleepALittle(milisSleep); } } } if (!connected && !finishedForGood) { dbg("NOT connected ", 1); // what, after all this trouble we are still not connected????!?!?!?! // let's communicate this to the user... String isAlive; try { int exitVal = process .exitValue(); // should throw exception saying that it still is not // terminated... isAlive = " - the process in NOT ALIVE anymore (output=" + exitVal + ") - "; } catch (IllegalThreadStateException e2) { // this is ok isAlive = " - the process in still alive (killing it now)- "; process.destroy(); } closeConn(); // make sure all connections are closed as we're not connected String msg = "Error connecting to python process (most likely cause for failure is a firewall blocking communication or a misconfigured network).\n" + isAlive + "\n" + processInfo.getProcessLog(); RuntimeException exception = new RuntimeException(msg); dbg(msg, 1); Log.log(exception); throw exception; } } catch (IOException e) { if (process != null) { process.destroy(); process = null; } throw e; } finally { if (processInfo != null) { processInfo.stopGettingOutput(); processInfo = null; } } } finally { this.inStart = false; } // if it got here, everything went ok (otherwise we would have gotten an exception). isConnected = true; } synchronized (lockLastPythonPath) { lastPythonPath = null; } }
/** When a console page is initialized, */ public void init(IPageBookViewPage page, final IConsole console) { if (!(console instanceof ProcessConsole)) { return; } ProcessConsole processConsole = (ProcessConsole) console; IProcess process = processConsole.getProcess(); if (process == null) { return; } if (!PyCodeCompletionPreferencesPage.useCodeCompletion() || !PyCodeCompletionPreferencesPage.useCodeCompletionOnDebug()) { return; } String attribute = process.getAttribute(Constants.PYDEV_DEBUG_IPROCESS_ATTR); if (!Constants.PYDEV_DEBUG_IPROCESS_ATTR_TRUE.equals(attribute)) { // Only provide code-completion for pydev debug processes. return; } Control control = page.getControl(); if (page instanceof IOConsolePage) { // Note that completions on "all letters and '_'" are already activated just by installing // the content assist, but the completions on the default keybinding is not, so, we have to // call it ourselves here. control.addKeyListener( new KeyListener() { public void keyPressed(KeyEvent e) { if (KeyBindingHelper.matchesContentAssistKeybinding(e)) { contentAssist.showPossibleCompletions(); } } public void keyReleased(KeyEvent e) {} }); IOConsolePage consolePage = (IOConsolePage) page; TextConsoleViewer viewer = consolePage.getViewer(); contentAssist = new PyContentAssistant() { public String showPossibleCompletions() { // Only show completions if we're in a suspended console. if (getCurrentSuspendedPyStackFrame(console) == null) { return null; } return super.showPossibleCompletions(); }; }; contentAssist.setInformationControlCreator( PyContentAssistant.createInformationControlCreator(viewer)); ILaunch launch = process.getLaunch(); IDebugTarget debugTarget = launch.getDebugTarget(); IInterpreterInfo projectInterpreter = null; if (debugTarget instanceof PyDebugTarget) { PyDebugTarget pyDebugTarget = (PyDebugTarget) debugTarget; PythonNature nature = PythonNature.getPythonNature(pyDebugTarget.project); if (nature != null) { try { projectInterpreter = nature.getProjectInterpreter(); } catch (Throwable e1) { Log.log(e1); } } } contentAssist.install(new ScriptConsoleViewerWrapper(viewer, projectInterpreter)); PydevConsoleInterpreter interpreter = new PydevConsoleInterpreter(); interpreter.setConsoleCommunication(new GetCompletionsInDebug()); IContentAssistProcessor processor = new PydevConsoleCompletionProcessor(interpreter, contentAssist); contentAssist.setContentAssistProcessor(processor, IOConsolePartition.INPUT_PARTITION_TYPE); contentAssist.setContentAssistProcessor(processor, IOConsolePartition.OUTPUT_PARTITION_TYPE); contentAssist.enableAutoActivation(true); contentAssist.enableAutoInsert(false); contentAssist.setAutoActivationDelay(PyCodeCompletionPreferencesPage.getAutocompleteDelay()); } }