From 92c42ef0d3da57efbc30ee924821dfbc4f2570db Mon Sep 17 00:00:00 2001 From: Piotr Tomiak Date: Fri, 30 Jan 2015 17:39:14 +0100 Subject: [PATCH] Issue #171: Preference for disabling asynchronous requests. https://github.com/angelozerr/tern.java/pull/232#issuecomment-71836103 --- .../src/tern/server/AbstractTernServer.java | 34 ++++--------- .../src/tern/server/ITernServer.java | 5 +- ....java => ITernServerRequestProcessor.java} | 6 +-- .../server/SynchronousRequestProcessor.java | 48 +++++++++++++++++++ .../TernCorePreferenceConstants.java | 1 + .../TernCorePreferencesSupport.java | 15 +++++- .../core/resources/IDETernProject.java | 9 ++-- .../IDETernServerAsyncReqProcessor.java | 20 ++++++-- .../ide/internal/ui/TernUIMessages.java | 2 + .../ide/internal/ui/TernUIMessages.properties | 1 + .../TernGlobalPreferencesPage.java | 14 ++++-- 11 files changed, 115 insertions(+), 40 deletions(-) rename core/tern.core/src/tern/server/{ITernServerAsyncRequestProcessor.java => ITernServerRequestProcessor.java} (73%) create mode 100644 core/tern.core/src/tern/server/SynchronousRequestProcessor.java diff --git a/core/tern.core/src/tern/server/AbstractTernServer.java b/core/tern.core/src/tern/server/AbstractTernServer.java index 33f816813..1d5b743a8 100644 --- a/core/tern.core/src/tern/server/AbstractTernServer.java +++ b/core/tern.core/src/tern/server/AbstractTernServer.java @@ -19,10 +19,8 @@ import tern.ITernFileSynchronizer; import tern.ITernProject; import tern.TernException; -import tern.server.protocol.ITernResultsAsyncCollector; import tern.server.protocol.ITernResultsCollector; import tern.server.protocol.TernDoc; -import tern.server.protocol.TernResultsProcessorsFactory; /** * Abstract tern server. @@ -38,7 +36,7 @@ public abstract class AbstractTernServer implements ITernServer { private boolean dispose; private boolean loadingLocalPlugins; - private ITernServerAsyncRequestProcessor asyncReqProcessor; + private ITernServerRequestProcessor reqProcessor; private ReentrantReadWriteLock stateLock = new ReentrantReadWriteLock(); @@ -161,34 +159,22 @@ public boolean isLoadingLocalPlugins() { @Override public void request(TernDoc doc, ITernResultsCollector collector) throws TernException { - ITernServerAsyncRequestProcessor asyncReqProc = this.asyncReqProcessor; - if (!(collector instanceof ITernResultsAsyncCollector)) { - try { - TernResultsProcessorsFactory.makeRequestAndProcess(doc, this, - collector); - } catch (TernException ex) { - throw ex; - } catch (Throwable t) { - throw new TernException(t); - } - } else if (asyncReqProc == null) { - throw new TernException( - "Cannot make an asynchronous request without an asynchronous request processor."); - } else { - asyncReqProc.processRequest(doc, - (ITernResultsAsyncCollector) collector); + if (reqProcessor == null) { + //always provide request processor + reqProcessor = new SynchronousRequestProcessor(this); } + reqProcessor.processRequest(doc, collector); } @Override - public ITernServerAsyncRequestProcessor getAsyncRequestProcessor() { - return asyncReqProcessor; + public ITernServerRequestProcessor getRequestProcessor() { + return reqProcessor; } @Override - public void setAsyncRequestProcessor( - ITernServerAsyncRequestProcessor asyncReqProcessor) { - this.asyncReqProcessor = asyncReqProcessor; + public void setRequestProcessor( + ITernServerRequestProcessor reqProcessor) { + this.reqProcessor = reqProcessor; } } diff --git a/core/tern.core/src/tern/server/ITernServer.java b/core/tern.core/src/tern/server/ITernServer.java index 117841a2f..12b673ce2 100644 --- a/core/tern.core/src/tern/server/ITernServer.java +++ b/core/tern.core/src/tern/server/ITernServer.java @@ -121,10 +121,9 @@ void request(TernDoc doc, ITernResultsCollector collector) */ boolean isLoadingLocalPlugins(); - ITernServerAsyncRequestProcessor getAsyncRequestProcessor(); + ITernServerRequestProcessor getRequestProcessor(); - void setAsyncRequestProcessor( - ITernServerAsyncRequestProcessor asyncReqProcessor); + void setRequestProcessor(ITernServerRequestProcessor asyncReqProcessor); IJSONObjectHelper getJSONObjectHelper(); diff --git a/core/tern.core/src/tern/server/ITernServerAsyncRequestProcessor.java b/core/tern.core/src/tern/server/ITernServerRequestProcessor.java similarity index 73% rename from core/tern.core/src/tern/server/ITernServerAsyncRequestProcessor.java rename to core/tern.core/src/tern/server/ITernServerRequestProcessor.java index 4f212ef00..baf76e1eb 100644 --- a/core/tern.core/src/tern/server/ITernServerAsyncRequestProcessor.java +++ b/core/tern.core/src/tern/server/ITernServerRequestProcessor.java @@ -11,12 +11,12 @@ package tern.server; import tern.TernException; -import tern.server.protocol.ITernResultsAsyncCollector; +import tern.server.protocol.ITernResultsCollector; import tern.server.protocol.TernDoc; -public interface ITernServerAsyncRequestProcessor { +public interface ITernServerRequestProcessor { - void processRequest(TernDoc doc, ITernResultsAsyncCollector collector) + void processRequest(TernDoc doc, ITernResultsCollector collector) throws TernException; } diff --git a/core/tern.core/src/tern/server/SynchronousRequestProcessor.java b/core/tern.core/src/tern/server/SynchronousRequestProcessor.java new file mode 100644 index 000000000..5e50164da --- /dev/null +++ b/core/tern.core/src/tern/server/SynchronousRequestProcessor.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2015 Genuitec LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Piotr Tomiak - initial API and implementation + */ +package tern.server; + +import tern.TernException; +import tern.server.protocol.ITernResultsAsyncCollector; +import tern.server.protocol.ITernResultsCollector; +import tern.server.protocol.TernDoc; +import tern.server.protocol.TernResultsProcessorsFactory; + +/** + * Basic request processor, which processes requests always in a synchronous + * way. + */ +public class SynchronousRequestProcessor implements ITernServerRequestProcessor { + + private ITernServer server; + + public SynchronousRequestProcessor(ITernServer server) { + this.server = server; + } + + @Override + public void processRequest(TernDoc doc, ITernResultsCollector collector) + throws TernException { + try { + TernResultsProcessorsFactory.makeRequestAndProcess(doc, server, + collector); + // mark collection as done to be super correct + if (collector instanceof ITernResultsAsyncCollector) { + ((ITernResultsAsyncCollector) collector).done(); + } + } catch (TernException ex) { + throw ex; + } catch (Throwable t) { + throw new TernException(t); + } + } + +} diff --git a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/core/preferences/TernCorePreferenceConstants.java b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/core/preferences/TernCorePreferenceConstants.java index 633fea030..68406f70a 100644 --- a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/core/preferences/TernCorePreferenceConstants.java +++ b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/core/preferences/TernCorePreferenceConstants.java @@ -24,6 +24,7 @@ public class TernCorePreferenceConstants { * Server preferences consttants. */ public static final String TERN_SERVER_TYPE = "ternServerType"; //$NON-NLS-1$ + public static final String DISABLE_ASYNC_REQUESTS = "disableAsyncRequests"; //$NON-NLS-1$ /** * Tern development preferences constants. diff --git a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/preferences/TernCorePreferencesSupport.java b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/preferences/TernCorePreferencesSupport.java index 871761c69..ce7490dbd 100644 --- a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/preferences/TernCorePreferencesSupport.java +++ b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/preferences/TernCorePreferencesSupport.java @@ -13,7 +13,6 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.Preferences; -import tern.eclipse.ide.core.ITernRepositoryManager; import tern.eclipse.ide.core.ITernServerType; import tern.eclipse.ide.core.TernCorePlugin; import tern.eclipse.ide.core.preferences.PreferencesSupport; @@ -78,6 +77,20 @@ public boolean isLoadingLocalPlugins(IProject project) { return StringUtils.asBoolean(result, false); } + /** + * Return false if Tern requests, like autocompletion should not be allowed + * to run asynchronously and timeout. + * + * @param project + * @return true if asynchronous requests should not be allowed. + */ + public boolean isDisableAsynchronousReques(IProject project) { + String result = preferencesSupport.getPreferencesValue( + TernCorePreferenceConstants.DISABLE_ASYNC_REQUESTS, null, + project); + return StringUtils.asBoolean(result, false); + } + /** * Returns the used tern repository name for the given project. * diff --git a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernProject.java b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernProject.java index a30deccfc..24c039096 100644 --- a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernProject.java +++ b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernProject.java @@ -148,9 +148,12 @@ public void onStop(ITernServer server) { getFileSynchronizer().cleanIndexedFiles(); } }); - this.ternServer - .setAsyncRequestProcessor(new IDETernServerAsyncReqProcessor( - ternServer)); + if (!TernCorePreferencesSupport.getInstance() + .isDisableAsynchronousReques(project)) { + this.ternServer + .setRequestProcessor(new IDETernServerAsyncReqProcessor( + ternServer)); + } copyListeners(); configureConsole(); } catch (Exception e) { diff --git a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernServerAsyncReqProcessor.java b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernServerAsyncReqProcessor.java index 16390fbb6..cc3ceda41 100644 --- a/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernServerAsyncReqProcessor.java +++ b/eclipse/tern.eclipse.ide.core/src/tern/eclipse/ide/internal/core/resources/IDETernServerAsyncReqProcessor.java @@ -18,14 +18,15 @@ import tern.TernException; import tern.eclipse.ide.core.TernCorePlugin; import tern.server.ITernServer; -import tern.server.ITernServerAsyncRequestProcessor; +import tern.server.ITernServerRequestProcessor; import tern.server.protocol.ITernResultsAsyncCollector; +import tern.server.protocol.ITernResultsCollector; import tern.server.protocol.TernResultsProcessorsFactory; import tern.server.protocol.ITernResultsAsyncCollector.TimeoutReason; import tern.server.protocol.TernDoc; public class IDETernServerAsyncReqProcessor extends Job implements - ITernServerAsyncRequestProcessor { + ITernServerRequestProcessor { private static final long TIMEOUT = 750; @@ -40,8 +41,21 @@ public IDETernServerAsyncReqProcessor(ITernServer server) { } @Override - public void processRequest(TernDoc doc, ITernResultsAsyncCollector collector) + public void processRequest(TernDoc doc, ITernResultsCollector c) throws TernException { + if (!(c instanceof ITernResultsAsyncCollector)) { + // need to process request synchronously + try { + TernResultsProcessorsFactory.makeRequestAndProcess(doc, server, + c); + return; + } catch (TernException ex) { + throw ex; + } catch (Throwable t) { + throw new TernException(t); + } + } + ITernResultsAsyncCollector collector = (ITernResultsAsyncCollector) c; long start = System.currentTimeMillis(); while (this.collector != null && (System.currentTimeMillis() - start) < TIMEOUT / 2) { diff --git a/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.java b/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.java index 71b6cf91a..665eddf8e 100644 --- a/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.java +++ b/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.java @@ -42,6 +42,8 @@ public final class TernUIMessages extends NLS { // Preferences public static String TernGlobalPreferencesPage_desc; + + public static String TernGlobalPreferencesPage_disable_async_reqs; public static String TernGlobalPreferencesPage_serverType; // Commons Property preferences diff --git a/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.properties b/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.properties index 8ff3684dd..cae07b64f 100644 --- a/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.properties +++ b/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/TernUIMessages.properties @@ -32,6 +32,7 @@ PropertyPreferencePage_01=Project Specific Configuration PropertyPreferencePage_02=Select the project to configure: TernGlobalPreferencesPage_desc=General Settings for using Tern. +TernGlobalPreferencesPage_disable_async_reqs=Disable asynchronous requests to Tern Server? TernGlobalPreferencesPage_serverType=Tern server type: # Properties page diff --git a/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/preferences/TernGlobalPreferencesPage.java b/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/preferences/TernGlobalPreferencesPage.java index 764646100..1ebb9ca91 100644 --- a/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/preferences/TernGlobalPreferencesPage.java +++ b/eclipse/tern.eclipse.ide.ui/src/tern/eclipse/ide/internal/ui/preferences/TernGlobalPreferencesPage.java @@ -12,6 +12,7 @@ import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IPreferenceStore; @@ -36,7 +37,8 @@ public class TernGlobalPreferencesPage extends FieldEditorPreferencePage public TernGlobalPreferencesPage() { super(GRID); setDescription(TernUIMessages.TernGlobalPreferencesPage_desc); - setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_LOGO)); + setImageDescriptor(ImageResource + .getImageDescriptor(ImageResource.IMG_LOGO)); } @Override @@ -46,8 +48,8 @@ protected void createFieldEditors() { ITernServerType[] serverTypes = TernCorePlugin .getTernServerTypeManager().getTernServerTypes(); String[][] types = new String[serverTypes.length + 1][2]; - types[0][0] = " -- Choose your server type --"; - types[0][1] = ""; + types[0][0] = " -- Choose your server type --"; //$NON-NLS-1$ + types[0][1] = ""; //$NON-NLS-1$ for (int i = 0; i < serverTypes.length; i++) { types[i + 1][0] = serverTypes[i].getName(); @@ -59,6 +61,12 @@ protected void createFieldEditors() { TernUIMessages.TernGlobalPreferencesPage_serverType, types, getFieldEditorParent()); addField(ternServerEditor); + + BooleanFieldEditor asyncRequestsEditor = new BooleanFieldEditor( + TernCorePreferenceConstants.DISABLE_ASYNC_REQUESTS, + TernUIMessages.TernGlobalPreferencesPage_disable_async_reqs, + getFieldEditorParent()); + addField(asyncRequestsEditor); } @Override